blob: 78c3ba4ec5104f882e0baf6a7b159c90ce2d0073 [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
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302288 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2289 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002290 if (adev->visualizer_start_output != NULL)
2291 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2292 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302293 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002294 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002297
2298 if (ret == 0) {
2299 register_out_stream(out);
2300 if (out->realtime) {
2301 ret = pcm_start(out->pcm);
2302 if (ret < 0)
2303 goto error_open;
2304 }
2305 }
2306
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302307 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002308 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002309
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002310 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002311error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302312 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002314error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302315 /*
2316 * sleep 50ms to allow sufficient time for kernel
2317 * drivers to recover incases like SSR.
2318 */
2319 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002320 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321}
2322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323static int check_input_parameters(uint32_t sample_rate,
2324 audio_format_t format,
2325 int channel_count)
2326{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002327 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302329 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2330 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2331 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002332 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302333 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002334
2335 switch (channel_count) {
2336 case 1:
2337 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302338 case 3:
2339 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002340 case 6:
2341 break;
2342 default:
2343 ret = -EINVAL;
2344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345
2346 switch (sample_rate) {
2347 case 8000:
2348 case 11025:
2349 case 12000:
2350 case 16000:
2351 case 22050:
2352 case 24000:
2353 case 32000:
2354 case 44100:
2355 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302356 case 96000:
2357 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 break;
2359 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002360 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 }
2362
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002363 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364}
2365
2366static size_t get_input_buffer_size(uint32_t sample_rate,
2367 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002368 int channel_count,
2369 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370{
2371 size_t size = 0;
2372
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002373 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2374 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002376 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002377 if (is_low_latency)
2378 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302379
2380 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002382 /* make sure the size is multiple of 32 bytes
2383 * At 48 kHz mono 16-bit PCM:
2384 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2385 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2386 */
2387 size += 0x1f;
2388 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002389
2390 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391}
2392
Ashish Jain058165c2016-09-28 23:18:48 +05302393static size_t get_output_period_size(uint32_t sample_rate,
2394 audio_format_t format,
2395 int channel_count,
2396 int duration /*in millisecs*/)
2397{
2398 size_t size = 0;
2399 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2400
2401 if ((duration == 0) || (sample_rate == 0) ||
2402 (bytes_per_sample == 0) || (channel_count == 0)) {
2403 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2404 bytes_per_sample, channel_count);
2405 return -EINVAL;
2406 }
2407
2408 size = (sample_rate *
2409 duration *
2410 bytes_per_sample *
2411 channel_count) / 1000;
2412 /*
2413 * To have same PCM samples for all channels, the buffer size requires to
2414 * be multiple of (number of channels * bytes per sample)
2415 * For writes to succeed, the buffer must be written at address which is multiple of 32
2416 */
2417 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2418
2419 return (size/(channel_count * bytes_per_sample));
2420}
2421
Ashish Jain5106d362016-05-11 19:23:33 +05302422static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2423{
2424 uint64_t actual_frames_rendered = 0;
2425 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2426
2427 /* This adjustment accounts for buffering after app processor.
2428 * It is based on estimated DSP latency per use case, rather than exact.
2429 */
2430 int64_t platform_latency = platform_render_latency(out->usecase) *
2431 out->sample_rate / 1000000LL;
2432
2433 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2434 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2435 * hence only estimate.
2436 */
2437 int64_t signed_frames = out->written - kernel_buffer_size;
2438
2439 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2440
2441 if (signed_frames > 0)
2442 actual_frames_rendered = signed_frames;
2443
2444 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2445 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2446 (long long int)out->written, (int)kernel_buffer_size,
2447 audio_bytes_per_sample(out->compr_config.codec->format),
2448 popcount(out->channel_mask));
2449
2450 return actual_frames_rendered;
2451}
2452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2454{
2455 struct stream_out *out = (struct stream_out *)stream;
2456
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002457 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458}
2459
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002460static int out_set_sample_rate(struct audio_stream *stream __unused,
2461 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462{
2463 return -ENOSYS;
2464}
2465
2466static size_t out_get_buffer_size(const struct audio_stream *stream)
2467{
2468 struct stream_out *out = (struct stream_out *)stream;
2469
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002470 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002471 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002472 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2473 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302474 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302475 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002476
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002477 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002478 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479}
2480
2481static uint32_t out_get_channels(const struct audio_stream *stream)
2482{
2483 struct stream_out *out = (struct stream_out *)stream;
2484
2485 return out->channel_mask;
2486}
2487
2488static audio_format_t out_get_format(const struct audio_stream *stream)
2489{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 struct stream_out *out = (struct stream_out *)stream;
2491
2492 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493}
2494
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002495static int out_set_format(struct audio_stream *stream __unused,
2496 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497{
2498 return -ENOSYS;
2499}
2500
2501static int out_standby(struct audio_stream *stream)
2502{
2503 struct stream_out *out = (struct stream_out *)stream;
2504 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002505
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302506 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2507 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002509 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002511 if (adev->adm_deregister_stream)
2512 adev->adm_deregister_stream(adev->adm_data, out->handle);
2513
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002514 if (is_offload_usecase(out->usecase))
2515 stop_compressed_output_l(out);
2516
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002517 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002519 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2520 voice_extn_compress_voip_close_output_stream(stream);
2521 pthread_mutex_unlock(&adev->lock);
2522 pthread_mutex_unlock(&out->lock);
2523 ALOGD("VOIP output entered standby");
2524 return 0;
2525 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 if (out->pcm) {
2527 pcm_close(out->pcm);
2528 out->pcm = NULL;
2529 }
2530 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002531 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302532 out->send_next_track_params = false;
2533 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002534 out->gapless_mdata.encoder_delay = 0;
2535 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002536 if (out->compr != NULL) {
2537 compress_close(out->compr);
2538 out->compr = NULL;
2539 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002540 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002542 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 }
2544 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302545 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 return 0;
2547}
2548
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002549static int out_dump(const struct audio_stream *stream __unused,
2550 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551{
2552 return 0;
2553}
2554
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002555static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2556{
2557 int ret = 0;
2558 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002559
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002560 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002561 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002562 return -EINVAL;
2563 }
2564
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302565 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002566
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002567 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2568 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302569 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002570 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002571 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2572 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302573 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002574 }
2575
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002576 ALOGV("%s new encoder delay %u and padding %u", __func__,
2577 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2578
2579 return 0;
2580}
2581
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002582static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2583{
2584 return out == adev->primary_output || out == adev->voice_tx_output;
2585}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2588{
2589 struct stream_out *out = (struct stream_out *)stream;
2590 struct audio_device *adev = out->dev;
2591 struct str_parms *parms;
2592 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002593 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594
sangwoobc677242013-08-08 16:53:43 +09002595 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002596 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302598 if (!parms)
2599 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002600 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2601 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002603 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002604 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002606 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002607 * When HDMI cable is unplugged the music playback is paused and
2608 * the policy manager sends routing=0. But the audioflinger continues
2609 * to write data until standby time (3sec). As the HDMI core is
2610 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002611 * Avoid this by routing audio to speaker until standby.
2612 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002613 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2614 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302615 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002616 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2617 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002618 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302619 /*
2620 * When A2DP is disconnected the
2621 * music playback is paused and the policy manager sends routing=0
2622 * But the audioflingercontinues to write data until standby time
2623 * (3sec). As BT is turned off, the write gets blocked.
2624 * Avoid this by routing audio to speaker until standby.
2625 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002626 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302627 (val == AUDIO_DEVICE_NONE)) {
2628 val = AUDIO_DEVICE_OUT_SPEAKER;
2629 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302630 /* To avoid a2dp to sco overlapping force route BT usecases
2631 * to speaker based on Phone state
2632 */
Ashish Jainc597d102016-12-12 10:31:34 +05302633 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2634 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2635 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2636 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302637 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2638 (adev->mode == AUDIO_MODE_IN_CALL))) {
2639 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2640 val = AUDIO_DEVICE_OUT_SPEAKER;
2641 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002642 /*
2643 * select_devices() call below switches all the usecases on the same
2644 * backend to the new device. Refer to check_usecases_codec_backend() in
2645 * the select_devices(). But how do we undo this?
2646 *
2647 * For example, music playback is active on headset (deep-buffer usecase)
2648 * and if we go to ringtones and select a ringtone, low-latency usecase
2649 * will be started on headset+speaker. As we can't enable headset+speaker
2650 * and headset devices at the same time, select_devices() switches the music
2651 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2652 * So when the ringtone playback is completed, how do we undo the same?
2653 *
2654 * We are relying on the out_set_parameters() call on deep-buffer output,
2655 * once the ringtone playback is ended.
2656 * NOTE: We should not check if the current devices are same as new devices.
2657 * Because select_devices() must be called to switch back the music
2658 * playback to headset.
2659 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002660 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002661 audio_devices_t new_dev = val;
2662 bool same_dev = out->devices == new_dev;
2663 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002664
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002665 if (output_drives_call(adev, out)) {
2666 if(!voice_is_in_call(adev)) {
2667 if (adev->mode == AUDIO_MODE_IN_CALL) {
2668 adev->current_call_output = out;
2669 ret = voice_start_call(adev);
2670 }
2671 } else {
2672 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002673 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002674 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002675 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002676
2677 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002678 if (!same_dev) {
2679 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302680 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2681 adev->perf_lock_opts,
2682 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002683 if (adev->adm_on_routing_change)
2684 adev->adm_on_routing_change(adev->adm_data,
2685 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002686 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002687 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302688 if (!same_dev)
2689 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002690 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002691 }
2692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002694 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002696
2697 if (out == adev->primary_output) {
2698 pthread_mutex_lock(&adev->lock);
2699 audio_extn_set_parameters(adev, parms);
2700 pthread_mutex_unlock(&adev->lock);
2701 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002702 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002703 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002704 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002705
2706 audio_extn_dts_create_state_notifier_node(out->usecase);
2707 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2708 popcount(out->channel_mask),
2709 out->playback_started);
2710
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002711 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002712 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002713
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302714 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2715 if (err >= 0) {
2716 strlcpy(out->profile, value, sizeof(out->profile));
2717 ALOGV("updating stream profile with value '%s'", out->profile);
2718 lock_output_stream(out);
2719 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2720 &adev->streams_output_cfg_list,
2721 out->devices, out->flags, out->format,
2722 out->sample_rate, out->bit_width,
2723 out->channel_mask, out->profile,
2724 &out->app_type_cfg);
2725 pthread_mutex_unlock(&out->lock);
2726 }
2727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302729error:
Eric Laurent994a6932013-07-17 11:51:42 -07002730 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 return ret;
2732}
2733
2734static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2735{
2736 struct stream_out *out = (struct stream_out *)stream;
2737 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002738 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 char value[256];
2740 struct str_parms *reply = str_parms_create();
2741 size_t i, j;
2742 int ret;
2743 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002744
2745 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002746 if (reply) {
2747 str_parms_destroy(reply);
2748 }
2749 if (query) {
2750 str_parms_destroy(query);
2751 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002752 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2753 return NULL;
2754 }
2755
Eric Laurent994a6932013-07-17 11:51:42 -07002756 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2758 if (ret >= 0) {
2759 value[0] = '\0';
2760 i = 0;
2761 while (out->supported_channel_masks[i] != 0) {
2762 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2763 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2764 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002765 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002767 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 first = false;
2769 break;
2770 }
2771 }
2772 i++;
2773 }
2774 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2775 str = str_parms_to_str(reply);
2776 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002777 voice_extn_out_get_parameters(out, query, reply);
2778 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002779 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002780 free(str);
2781 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002782 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002784
Alexy Joseph62142aa2015-11-16 15:10:34 -08002785
2786 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2787 if (ret >= 0) {
2788 value[0] = '\0';
2789 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2790 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302791 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002792 } else {
2793 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302794 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002795 }
2796 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002797 if (str)
2798 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002799 str = str_parms_to_str(reply);
2800 }
2801
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002802 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2803 if (ret >= 0) {
2804 value[0] = '\0';
2805 i = 0;
2806 first = true;
2807 while (out->supported_formats[i] != 0) {
2808 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2809 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2810 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002811 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002812 }
2813 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2814 first = false;
2815 break;
2816 }
2817 }
2818 i++;
2819 }
2820 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002821 if (str)
2822 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002823 str = str_parms_to_str(reply);
2824 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002825
2826 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2827 if (ret >= 0) {
2828 value[0] = '\0';
2829 i = 0;
2830 first = true;
2831 while (out->supported_sample_rates[i] != 0) {
2832 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2833 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2834 if (!first) {
2835 strlcat(value, "|", sizeof(value));
2836 }
2837 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2838 first = false;
2839 break;
2840 }
2841 }
2842 i++;
2843 }
2844 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2845 if (str)
2846 free(str);
2847 str = str_parms_to_str(reply);
2848 }
2849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 str_parms_destroy(query);
2851 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002852 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 return str;
2854}
2855
2856static uint32_t out_get_latency(const struct audio_stream_out *stream)
2857{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002858 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002860 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861
Alexy Josephaa54c872014-12-03 02:46:47 -08002862 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002863 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002864 } else if (out->realtime) {
2865 // since the buffer won't be filled up faster than realtime,
2866 // return a smaller number
2867 if (out->config.rate)
2868 period_ms = (out->af_period_multiplier * out->config.period_size *
2869 1000) / (out->config.rate);
2870 else
2871 period_ms = 0;
2872 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002873 } else {
2874 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002876 }
2877
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302878 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002879 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880}
2881
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302882static float AmpToDb(float amplification)
2883{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302884 float db = DSD_VOLUME_MIN_DB;
2885 if (amplification > 0) {
2886 db = 20 * log10(amplification);
2887 if(db < DSD_VOLUME_MIN_DB)
2888 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302889 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302890 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302891}
2892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893static int out_set_volume(struct audio_stream_out *stream, float left,
2894 float right)
2895{
Eric Laurenta9024de2013-04-04 09:19:12 -07002896 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897 int volume[2];
2898
Eric Laurenta9024de2013-04-04 09:19:12 -07002899 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2900 /* only take left channel into account: the API is for stereo anyway */
2901 out->muted = (left == 0.0f);
2902 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002903 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302904 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002905 /*
2906 * Set mute or umute on HDMI passthrough stream.
2907 * Only take left channel into account.
2908 * Mute is 0 and unmute 1
2909 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302910 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302911 } else if (out->format == AUDIO_FORMAT_DSD){
2912 char mixer_ctl_name[128] = "DSD Volume";
2913 struct audio_device *adev = out->dev;
2914 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2915
2916 if (!ctl) {
2917 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2918 __func__, mixer_ctl_name);
2919 return -EINVAL;
2920 }
2921 volume[0] = (int)(AmpToDb(left));
2922 volume[1] = (int)(AmpToDb(right));
2923 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2924 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002925 } else {
2926 char mixer_ctl_name[128];
2927 struct audio_device *adev = out->dev;
2928 struct mixer_ctl *ctl;
2929 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002930 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002931
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002932 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2933 "Compress Playback %d Volume", pcm_device_id);
2934 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2935 if (!ctl) {
2936 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2937 __func__, mixer_ctl_name);
2938 return -EINVAL;
2939 }
2940 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2941 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2942 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2943 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002945 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947 return -ENOSYS;
2948}
2949
2950static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2951 size_t bytes)
2952{
2953 struct stream_out *out = (struct stream_out *)stream;
2954 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302955 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002956 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002958 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302959
Naresh Tanniru80659832014-06-04 18:17:56 +05302960 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002961
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302962 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302963 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302964 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2965 pthread_mutex_unlock(&out->lock);
2966 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302967 } else {
2968 /* increase written size during SSR to avoid mismatch
2969 * with the written frames count in AF
2970 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002971 // bytes per frame
2972 size_t bpf = audio_bytes_per_sample(out->format) *
2973 audio_channel_count_from_out_mask(out->channel_mask);
2974 if (bpf != 0)
2975 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302976 ALOGD(" %s: sound card is not active/SSR state", __func__);
2977 ret= -EIO;
2978 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302979 }
2980 }
2981
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302982 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302983 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2984 if (audio_bytes_per_sample(out->format) != 0)
2985 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2986 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302987 goto exit;
2988 }
2989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002991 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002992 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002993 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2994 ret = voice_extn_compress_voip_start_output_stream(out);
2995 else
2996 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002997 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003000 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 goto exit;
3002 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003003
3004 if (last_known_cal_step != -1) {
3005 ALOGD("%s: retry previous failed cal level set", __func__);
3006 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009
Ashish Jain81eb2a82015-05-13 10:52:34 +05303010 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003011 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303012 adev->is_channel_status_set = true;
3013 }
3014
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003015 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003016 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003017 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003018 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003019 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3020 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303021 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3022 ALOGD("copl(%p):send next track params in gapless", out);
3023 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3024 out->send_next_track_params = false;
3025 out->is_compr_metadata_avail = false;
3026 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003027 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303028 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303029 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003030
Ashish Jain83a6cc22016-06-28 14:34:17 +05303031 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303032 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303033 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303034 pthread_mutex_unlock(&out->lock);
3035 return -EINVAL;
3036 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303037 audio_format_t dst_format = out->hal_op_format;
3038 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303039
3040 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3041 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3042
Ashish Jain83a6cc22016-06-28 14:34:17 +05303043 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303044 dst_format,
3045 buffer,
3046 src_format,
3047 frames);
3048
Ashish Jain83a6cc22016-06-28 14:34:17 +05303049 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303050 bytes_to_write);
3051
3052 /*Convert written bytes in audio flinger format*/
3053 if (ret > 0)
3054 ret = ((ret * format_to_bitwidth_table[out->format]) /
3055 format_to_bitwidth_table[dst_format]);
3056 }
3057 } else
3058 ret = compress_write(out->compr, buffer, bytes);
3059
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303060 if (ret < 0)
3061 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303062 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303063 /*msg to cb thread only if non blocking write is enabled*/
3064 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303065 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303067 } else if (-ENETRESET == ret) {
3068 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3069 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3070 pthread_mutex_unlock(&out->lock);
3071 out_standby(&out->stream.common);
3072 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 }
Ashish Jain5106d362016-05-11 19:23:33 +05303074 if ( ret == (ssize_t)bytes && !out->non_blocking)
3075 out->written += bytes;
3076
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303077 /* Call compr start only when non-zero bytes of data is there to be rendered */
3078 if (!out->playback_started && ret > 0) {
3079 int status = compress_start(out->compr);
3080 if (status < 0) {
3081 ret = status;
3082 ALOGE("%s: compr start failed with err %d", __func__, errno);
3083 goto exit;
3084 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003085 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003086 out->playback_started = 1;
3087 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003088
3089 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3090 popcount(out->channel_mask),
3091 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092 }
3093 pthread_mutex_unlock(&out->lock);
3094 return ret;
3095 } else {
3096 if (out->pcm) {
3097 if (out->muted)
3098 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003099
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303100 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003101
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003102 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003103
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003104 if (out->config.rate)
3105 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3106 out->config.rate;
3107
3108 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3109
3110 request_out_focus(out, ns);
3111
3112 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003113 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003114 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303115 out->convert_buffer != NULL) {
3116
3117 memcpy_by_audio_format(out->convert_buffer,
3118 out->hal_op_format,
3119 buffer,
3120 out->hal_ip_format,
3121 out->config.period_size * out->config.channels);
3122
3123 ret = pcm_write(out->pcm, out->convert_buffer,
3124 (out->config.period_size *
3125 out->config.channels *
3126 format_to_bitwidth_table[out->hal_op_format]));
3127 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003128 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303129 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003130
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003131 release_out_focus(out);
3132
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303133 if (ret < 0)
3134 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303135 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3136 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3137 else
3138 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 }
3141
3142exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303143 /* ToDo: There may be a corner case when SSR happens back to back during
3144 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303145 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303146 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303147 }
3148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 pthread_mutex_unlock(&out->lock);
3150
3151 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003152 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003153 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303154 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303155 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303156 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303157 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303158 out->standby = true;
3159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303161 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3162 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3163 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 }
3165 return bytes;
3166}
3167
3168static int out_get_render_position(const struct audio_stream_out *stream,
3169 uint32_t *dsp_frames)
3170{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003171 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303172 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003173
3174 if (dsp_frames == NULL)
3175 return -EINVAL;
3176
3177 *dsp_frames = 0;
3178 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003179 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303180
3181 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3182 * this operation and adev_close_output_stream(where out gets reset).
3183 */
3184 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3185 *dsp_frames = get_actual_pcm_frames_rendered(out);
3186 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3187 return 0;
3188 }
3189
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003190 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303191 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303192 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303194 if (ret < 0)
3195 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003196 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303197 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198 }
3199 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303200 if (-ENETRESET == ret) {
3201 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3202 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3203 return -EINVAL;
3204 } else if(ret < 0) {
3205 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3206 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303207 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3208 /*
3209 * Handle corner case where compress session is closed during SSR
3210 * and timestamp is queried
3211 */
3212 ALOGE(" ERROR: sound card not active, return error");
3213 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303214 } else {
3215 return 0;
3216 }
Zhou Song32a556e2015-05-05 10:46:56 +08003217 } else if (audio_is_linear_pcm(out->format)) {
3218 *dsp_frames = out->written;
3219 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003220 } else
3221 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222}
3223
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003224static int out_add_audio_effect(const struct audio_stream *stream __unused,
3225 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226{
3227 return 0;
3228}
3229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003230static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3231 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232{
3233 return 0;
3234}
3235
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003236static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3237 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238{
3239 return -EINVAL;
3240}
3241
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003242static int out_get_presentation_position(const struct audio_stream_out *stream,
3243 uint64_t *frames, struct timespec *timestamp)
3244{
3245 struct stream_out *out = (struct stream_out *)stream;
3246 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003247 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003248
Ashish Jain5106d362016-05-11 19:23:33 +05303249 /* below piece of code is not guarded against any lock because audioFliner serializes
3250 * this operation and adev_close_output_stream( where out gets reset).
3251 */
3252 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3253 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3254 *frames = get_actual_pcm_frames_rendered(out);
3255 /* this is the best we can do */
3256 clock_gettime(CLOCK_MONOTONIC, timestamp);
3257 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3258 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3259 return 0;
3260 }
3261
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003262 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003263
Ashish Jain5106d362016-05-11 19:23:33 +05303264 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3265 ret = compress_get_tstamp(out->compr, &dsp_frames,
3266 &out->sample_rate);
3267 ALOGVV("%s rendered frames %ld sample_rate %d",
3268 __func__, dsp_frames, out->sample_rate);
3269 *frames = dsp_frames;
3270 if (ret < 0)
3271 ret = -errno;
3272 if (-ENETRESET == ret) {
3273 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3274 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3275 ret = -EINVAL;
3276 } else
3277 ret = 0;
3278 /* this is the best we can do */
3279 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003280 } else {
3281 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003282 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003283 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3284 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003285 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003286 // This adjustment accounts for buffering after app processor.
3287 // It is based on estimated DSP latency per use case, rather than exact.
3288 signed_frames -=
3289 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3290
Eric Laurent949a0892013-09-20 09:20:13 -07003291 // It would be unusual for this value to be negative, but check just in case ...
3292 if (signed_frames >= 0) {
3293 *frames = signed_frames;
3294 ret = 0;
3295 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003296 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303297 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3298 *frames = out->written;
3299 clock_gettime(CLOCK_MONOTONIC, timestamp);
3300 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003301 }
3302 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003303 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003304 return ret;
3305}
3306
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003307static int out_set_callback(struct audio_stream_out *stream,
3308 stream_callback_t callback, void *cookie)
3309{
3310 struct stream_out *out = (struct stream_out *)stream;
3311
3312 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003313 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003314 out->offload_callback = callback;
3315 out->offload_cookie = cookie;
3316 pthread_mutex_unlock(&out->lock);
3317 return 0;
3318}
3319
3320static int out_pause(struct audio_stream_out* stream)
3321{
3322 struct stream_out *out = (struct stream_out *)stream;
3323 int status = -ENOSYS;
3324 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003325 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003326 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003327 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003328 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303329 struct audio_device *adev = out->dev;
3330 int snd_scard_state = get_snd_card_state(adev);
3331
3332 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3333 status = compress_pause(out->compr);
3334
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003336
Mingming Yin21854652016-04-13 11:54:02 -07003337 if (audio_extn_passthru_is_active()) {
3338 ALOGV("offload use case, pause passthru");
3339 audio_extn_passthru_on_pause(out);
3340 }
3341
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303342 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003343 audio_extn_dts_notify_playback_state(out->usecase, 0,
3344 out->sample_rate, popcount(out->channel_mask),
3345 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003346 }
3347 pthread_mutex_unlock(&out->lock);
3348 }
3349 return status;
3350}
3351
3352static int out_resume(struct audio_stream_out* stream)
3353{
3354 struct stream_out *out = (struct stream_out *)stream;
3355 int status = -ENOSYS;
3356 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003357 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003358 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003359 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003360 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003361 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303362 struct audio_device *adev = out->dev;
3363 int snd_scard_state = get_snd_card_state(adev);
3364
Mingming Yin21854652016-04-13 11:54:02 -07003365 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3366 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3367 pthread_mutex_lock(&out->dev->lock);
3368 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003369 pthread_mutex_unlock(&out->dev->lock);
3370 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303371 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003372 }
3373 if (!status) {
3374 out->offload_state = OFFLOAD_STATE_PLAYING;
3375 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303376 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003377 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3378 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 }
3380 pthread_mutex_unlock(&out->lock);
3381 }
3382 return status;
3383}
3384
3385static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3386{
3387 struct stream_out *out = (struct stream_out *)stream;
3388 int status = -ENOSYS;
3389 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003390 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003391 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003392 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3393 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3394 else
3395 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3396 pthread_mutex_unlock(&out->lock);
3397 }
3398 return status;
3399}
3400
3401static int out_flush(struct audio_stream_out* stream)
3402{
3403 struct stream_out *out = (struct stream_out *)stream;
3404 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003405 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003406 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003407 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003408 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3409 stop_compressed_output_l(out);
3410 out->written = 0;
3411 } else {
3412 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3413 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003415 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003416 return 0;
3417 }
3418 return -ENOSYS;
3419}
3420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421/** audio_stream_in implementation **/
3422static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3423{
3424 struct stream_in *in = (struct stream_in *)stream;
3425
3426 return in->config.rate;
3427}
3428
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003429static int in_set_sample_rate(struct audio_stream *stream __unused,
3430 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431{
3432 return -ENOSYS;
3433}
3434
3435static size_t in_get_buffer_size(const struct audio_stream *stream)
3436{
3437 struct stream_in *in = (struct stream_in *)stream;
3438
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003439 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3440 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003441 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3442 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303443 else if(audio_extn_cin_attached_usecase(in->usecase))
3444 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003445
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003446 return in->config.period_size * in->af_period_multiplier *
3447 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448}
3449
3450static uint32_t in_get_channels(const struct audio_stream *stream)
3451{
3452 struct stream_in *in = (struct stream_in *)stream;
3453
3454 return in->channel_mask;
3455}
3456
3457static audio_format_t in_get_format(const struct audio_stream *stream)
3458{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003459 struct stream_in *in = (struct stream_in *)stream;
3460
3461 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462}
3463
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003464static int in_set_format(struct audio_stream *stream __unused,
3465 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466{
3467 return -ENOSYS;
3468}
3469
3470static int in_standby(struct audio_stream *stream)
3471{
3472 struct stream_in *in = (struct stream_in *)stream;
3473 struct audio_device *adev = in->dev;
3474 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303475 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3476 stream, in->usecase, use_case_table[in->usecase]);
3477
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003478 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003479 if (!in->standby && in->is_st_session) {
3480 ALOGD("%s: sound trigger pcm stop lab", __func__);
3481 audio_extn_sound_trigger_stop_lab(in);
3482 in->standby = 1;
3483 }
3484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003486 if (adev->adm_deregister_stream)
3487 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3488
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003489 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003491 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3492 voice_extn_compress_voip_close_input_stream(stream);
3493 ALOGD("VOIP input entered standby");
3494 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303495 if (audio_extn_cin_attached_usecase(in->usecase))
3496 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003497 if (in->pcm) {
3498 pcm_close(in->pcm);
3499 in->pcm = NULL;
3500 }
3501 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003502 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003503 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 }
3505 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003506 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 return status;
3508}
3509
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003510static int in_dump(const struct audio_stream *stream __unused,
3511 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512{
3513 return 0;
3514}
3515
3516static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3517{
3518 struct stream_in *in = (struct stream_in *)stream;
3519 struct audio_device *adev = in->dev;
3520 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003522 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303524 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 parms = str_parms_create_str(kvpairs);
3526
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303527 if (!parms)
3528 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003529 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003530 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003531
3532 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3533 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 val = atoi(value);
3535 /* no audio source uses val == 0 */
3536 if ((in->source != val) && (val != 0)) {
3537 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003538 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3539 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3540 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003541 (in->config.rate == 8000 || in->config.rate == 16000 ||
3542 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003543 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003544 err = voice_extn_compress_voip_open_input_stream(in);
3545 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003546 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003547 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003548 }
3549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 }
3551 }
3552
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003553 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3554 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003556 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 in->device = val;
3558 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003559 if (!in->standby && !in->is_st_session) {
3560 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003561 if (adev->adm_on_routing_change)
3562 adev->adm_on_routing_change(adev->adm_data,
3563 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003564 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003565 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 }
3567 }
3568
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303569 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3570 if (err >= 0) {
3571 strlcpy(in->profile, value, sizeof(in->profile));
3572 ALOGV("updating stream profile with value '%s'", in->profile);
3573 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3574 &adev->streams_input_cfg_list,
3575 in->device, in->flags, in->format,
3576 in->sample_rate, in->bit_width,
3577 in->profile, &in->app_type_cfg);
3578 }
3579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003581 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582
3583 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303584error:
Eric Laurent994a6932013-07-17 11:51:42 -07003585 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586 return ret;
3587}
3588
3589static char* in_get_parameters(const struct audio_stream *stream,
3590 const char *keys)
3591{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003592 struct stream_in *in = (struct stream_in *)stream;
3593 struct str_parms *query = str_parms_create_str(keys);
3594 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003595 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003596
3597 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003598 if (reply) {
3599 str_parms_destroy(reply);
3600 }
3601 if (query) {
3602 str_parms_destroy(query);
3603 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003604 ALOGE("in_get_parameters: failed to create query or reply");
3605 return NULL;
3606 }
3607
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003608 ALOGV("%s: enter: keys - %s", __func__, keys);
3609
3610 voice_extn_in_get_parameters(in, query, reply);
3611
3612 str = str_parms_to_str(reply);
3613 str_parms_destroy(query);
3614 str_parms_destroy(reply);
3615
3616 ALOGV("%s: exit: returns - %s", __func__, str);
3617 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618}
3619
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003620static int in_set_gain(struct audio_stream_in *stream __unused,
3621 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622{
3623 return 0;
3624}
3625
3626static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3627 size_t bytes)
3628{
3629 struct stream_in *in = (struct stream_in *)stream;
3630 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303631 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303632 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303633 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003635 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303636
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003637 if (in->is_st_session) {
3638 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3639 /* Read from sound trigger HAL */
3640 audio_extn_sound_trigger_read(in, buffer, bytes);
3641 pthread_mutex_unlock(&in->lock);
3642 return bytes;
3643 }
3644
Ashish Jainbbce4322016-02-16 13:25:27 +05303645 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003646 ALOGD(" %s: sound card is not active/SSR state", __func__);
3647 ret= -EIO;;
3648 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303649 }
3650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003652 pthread_mutex_lock(&adev->lock);
3653 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3654 ret = voice_extn_compress_voip_start_input_stream(in);
3655 else
3656 ret = start_input_stream(in);
3657 pthread_mutex_unlock(&adev->lock);
3658 if (ret != 0) {
3659 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 }
3661 in->standby = 0;
3662 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003664 // what's the duration requested by the client?
3665 long ns = 0;
3666
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303667 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003668 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3669 in->config.rate;
3670
3671 request_in_focus(in, ns);
3672 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003673
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303674 if (audio_extn_cin_attached_usecase(in->usecase)) {
3675 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3676 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303677 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003678 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303679 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003680 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003681 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003682 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303683 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003684 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303685 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3686 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3687 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3688 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303689 ret = -EINVAL;
3690 goto exit;
3691 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303692 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303693 ret = -errno;
3694 }
3695 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303696 /* bytes read is always set to bytes for non compress usecases */
3697 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698 }
3699
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003700 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 /*
3703 * Instead of writing zeroes here, we could trust the hardware
3704 * to always provide zeroes when muted.
3705 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303706 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3707 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 memset(buffer, 0, bytes);
3709
3710exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303711 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303712 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003713 if (-ENETRESET == ret)
3714 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 pthread_mutex_unlock(&in->lock);
3717
3718 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303719 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303720 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303721 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303722 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303723 in->standby = true;
3724 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303725 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003727 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303728 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303729 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303731 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732}
3733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003734static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735{
3736 return 0;
3737}
3738
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003739static int add_remove_audio_effect(const struct audio_stream *stream,
3740 effect_handle_t effect,
3741 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003743 struct stream_in *in = (struct stream_in *)stream;
3744 int status = 0;
3745 effect_descriptor_t desc;
3746
3747 status = (*effect)->get_descriptor(effect, &desc);
3748 if (status != 0)
3749 return status;
3750
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003751 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003752 pthread_mutex_lock(&in->dev->lock);
3753 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3754 in->enable_aec != enable &&
3755 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3756 in->enable_aec = enable;
3757 if (!in->standby)
3758 select_devices(in->dev, in->usecase);
3759 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003760 if (in->enable_ns != enable &&
3761 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3762 in->enable_ns = enable;
3763 if (!in->standby)
3764 select_devices(in->dev, in->usecase);
3765 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003766 pthread_mutex_unlock(&in->dev->lock);
3767 pthread_mutex_unlock(&in->lock);
3768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 return 0;
3770}
3771
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003772static int in_add_audio_effect(const struct audio_stream *stream,
3773 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774{
Eric Laurent994a6932013-07-17 11:51:42 -07003775 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003776 return add_remove_audio_effect(stream, effect, true);
3777}
3778
3779static int in_remove_audio_effect(const struct audio_stream *stream,
3780 effect_handle_t effect)
3781{
Eric Laurent994a6932013-07-17 11:51:42 -07003782 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003783 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784}
3785
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303786int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 audio_io_handle_t handle,
3788 audio_devices_t devices,
3789 audio_output_flags_t flags,
3790 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003791 struct audio_stream_out **stream_out,
3792 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793{
3794 struct audio_device *adev = (struct audio_device *)dev;
3795 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303796 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003797 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303800
3801 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3802 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003803 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303804 return -EINVAL;
3805 }
3806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3808
Mingming Yin3a941d42016-02-17 18:08:05 -08003809 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3810 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303811 devices, flags, &out->stream);
3812
3813
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003814 if (!out) {
3815 return -ENOMEM;
3816 }
3817
Haynes Mathew George204045b2015-02-25 20:32:03 -08003818 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003819 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003820 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 if (devices == AUDIO_DEVICE_NONE)
3823 devices = AUDIO_DEVICE_OUT_SPEAKER;
3824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 out->flags = flags;
3826 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003827 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003828 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003829 out->sample_rate = config->sample_rate;
3830 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3831 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003832 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003833 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003834 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303835 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836
Mingming Yin3a941d42016-02-17 18:08:05 -08003837 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3838 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3839 pthread_mutex_lock(&adev->lock);
3840 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3841 ret = read_hdmi_sink_caps(out);
3842 pthread_mutex_unlock(&adev->lock);
3843 if (ret != 0) {
3844 if (ret == -ENOSYS) {
3845 /* ignore and go with default */
3846 ret = 0;
3847 } else {
3848 ALOGE("error reading hdmi sink caps");
3849 goto error_open;
3850 }
3851 }
3852 }
3853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003855 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303856 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3857 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003858 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3859 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3860
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003861 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003862 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3863 /*
3864 * Do not handle stereo output in Multi-channel cases
3865 * Stereo case is handled in normal playback path
3866 */
3867 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3868 ret = AUDIO_CHANNEL_OUT_STEREO;
3869 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003870
3871 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3872 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003873 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003874 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003875 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003876
3877 if (config->sample_rate == 0)
3878 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3879 if (config->channel_mask == 0)
3880 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003881 if (config->format == 0)
3882 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003883
3884 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003885 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003886 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3888 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003890 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003892 } 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 -08003893 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003894 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003895 ret = voice_extn_compress_voip_open_output_stream(out);
3896 if (ret != 0) {
3897 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3898 __func__, ret);
3899 goto error_open;
3900 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003901 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3902 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3903
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003904 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3905 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3906 ALOGE("%s: Unsupported Offload information", __func__);
3907 ret = -EINVAL;
3908 goto error_open;
3909 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003910
Mingming Yin3a941d42016-02-17 18:08:05 -08003911 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003912 if(config->offload_info.format == 0)
3913 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003914 if (config->offload_info.sample_rate == 0)
3915 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003916 }
3917
Mingming Yin90310102013-11-13 16:57:00 -08003918 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303919 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003920 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003921 ret = -EINVAL;
3922 goto error_open;
3923 }
3924
3925 out->compr_config.codec = (struct snd_codec *)
3926 calloc(1, sizeof(struct snd_codec));
3927
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003928 if (!out->compr_config.codec) {
3929 ret = -ENOMEM;
3930 goto error_open;
3931 }
3932
vivek mehta0ea887a2015-08-26 14:01:20 -07003933 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303934 out->stream.pause = out_pause;
3935 out->stream.flush = out_flush;
3936 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003937 out->usecase = get_offload_usecase(adev, true);
3938 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003939 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003940 out->stream.set_callback = out_set_callback;
3941 out->stream.pause = out_pause;
3942 out->stream.resume = out_resume;
3943 out->stream.drain = out_drain;
3944 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003945 out->usecase = get_offload_usecase(adev, false);
3946 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003947 }
vivek mehta446c3962015-09-14 10:57:35 -07003948
3949 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003950 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3951 config->format == 0 && config->sample_rate == 0 &&
3952 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003953 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003954 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3955 } else {
3956 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3957 ret = -EEXIST;
3958 goto error_open;
3959 }
vivek mehta446c3962015-09-14 10:57:35 -07003960 }
3961
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003962 if (config->offload_info.channel_mask)
3963 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003964 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003965 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003966 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003967 } else {
3968 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3969 ret = -EINVAL;
3970 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003971 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003972
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003973 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003974 out->sample_rate = config->offload_info.sample_rate;
3975
Mingming Yin3ee55c62014-08-04 14:23:35 -07003976 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003977
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303978 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3979 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3980 audio_extn_dolby_send_ddp_endp_params(adev);
3981 audio_extn_dolby_set_dmid(adev);
3982 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003985 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003986 out->compr_config.codec->bit_rate =
3987 config->offload_info.bit_rate;
3988 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303989 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003990 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05303991 /* Update bit width only for non passthrough usecases.
3992 * For passthrough usecases, the output will always be opened @16 bit
3993 */
3994 if (!audio_extn_passthru_is_passthrough_stream(out))
3995 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003996 /*TODO: Do we need to change it for passthrough */
3997 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003998
Manish Dewangana6fc5442015-08-24 20:30:31 +05303999 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4000 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304001 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304002 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304003 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4004 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304005
4006 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4007 AUDIO_FORMAT_PCM) {
4008
4009 /*Based on platform support, configure appropriate alsa format for corresponding
4010 *hal input format.
4011 */
4012 out->compr_config.codec->format = hal_format_to_alsa(
4013 config->offload_info.format);
4014
Ashish Jain83a6cc22016-06-28 14:34:17 +05304015 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304016 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304017 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304018
4019 /*for direct PCM playback populate bit_width based on selected alsa format as
4020 *hal input format and alsa format might differ based on platform support.
4021 */
4022 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304023 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304024
4025 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4026
4027 /* Check if alsa session is configured with the same format as HAL input format,
4028 * if not then derive correct fragment size needed to accomodate the
4029 * conversion of HAL input format to alsa format.
4030 */
4031 audio_extn_utils_update_direct_pcm_fragment_size(out);
4032
4033 /*if hal input and output fragment size is different this indicates HAL input format is
4034 *not same as the alsa format
4035 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304036 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304037 /*Allocate a buffer to convert input data to the alsa configured format.
4038 *size of convert buffer is equal to the size required to hold one fragment size
4039 *worth of pcm data, this is because flinger does not write more than fragment_size
4040 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304041 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4042 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304043 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4044 ret = -ENOMEM;
4045 goto error_open;
4046 }
4047 }
4048 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4049 out->compr_config.fragment_size =
4050 audio_extn_passthru_get_buffer_size(&config->offload_info);
4051 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4052 } else {
4053 out->compr_config.fragment_size =
4054 platform_get_compress_offload_buffer_size(&config->offload_info);
4055 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4056 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004057
Amit Shekhar6f461b12014-08-01 14:52:58 -07004058 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304059 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004060
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304061 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4062 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4063 }
4064
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004065 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4066 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004067
Alexy Josephaa54c872014-12-03 02:46:47 -08004068
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004069 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304070 out->send_next_track_params = false;
4071 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004072 out->offload_state = OFFLOAD_STATE_IDLE;
4073 out->playback_started = 0;
4074
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004075 audio_extn_dts_create_state_notifier_node(out->usecase);
4076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004077 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4078 __func__, config->offload_info.version,
4079 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304080
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304081 /* Check if DSD audio format is supported in codec
4082 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304083 */
4084
4085 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304086 (!platform_check_codec_dsd_support(adev->platform) ||
4087 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304088 ret = -EINVAL;
4089 goto error_open;
4090 }
4091
Ashish Jain5106d362016-05-11 19:23:33 +05304092 /* Disable gapless if any of the following is true
4093 * passthrough playback
4094 * AV playback
4095 * Direct PCM playback
4096 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304097 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304098 (config->format == AUDIO_FORMAT_DSD) ||
4099 config->offload_info.has_video ||
4100 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304101 check_and_set_gapless_mode(adev, false);
4102 } else
4103 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004104
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304105 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004106 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4107 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304108 if (config->format == AUDIO_FORMAT_DSD) {
4109 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4110 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4111 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004112
4113 create_offload_callback_thread(out);
4114
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004115 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304116 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004117 if (ret != 0) {
4118 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4119 __func__, ret);
4120 goto error_open;
4121 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004122 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4123 if (config->sample_rate == 0)
4124 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4125 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4126 config->sample_rate != 8000) {
4127 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4128 ret = -EINVAL;
4129 goto error_open;
4130 }
4131 out->sample_rate = config->sample_rate;
4132 out->config.rate = config->sample_rate;
4133 if (config->format == AUDIO_FORMAT_DEFAULT)
4134 config->format = AUDIO_FORMAT_PCM_16_BIT;
4135 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4136 config->format = AUDIO_FORMAT_PCM_16_BIT;
4137 ret = -EINVAL;
4138 goto error_open;
4139 }
4140 out->format = config->format;
4141 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4142 out->config = pcm_config_afe_proxy_playback;
4143 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004144 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304145 unsigned int channels = 0;
4146 /*Update config params to default if not set by the caller*/
4147 if (config->sample_rate == 0)
4148 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4149 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4150 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4151 if (config->format == AUDIO_FORMAT_DEFAULT)
4152 config->format = AUDIO_FORMAT_PCM_16_BIT;
4153
4154 channels = audio_channel_count_from_out_mask(out->channel_mask);
4155
Ashish Jain83a6cc22016-06-28 14:34:17 +05304156 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4157 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004158 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4159 out->flags);
4160 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304161 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4162 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4163 out->config = pcm_config_low_latency;
4164 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4165 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4166 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304167 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4168 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4169 if (out->config.period_size <= 0) {
4170 ALOGE("Invalid configuration period size is not valid");
4171 ret = -EINVAL;
4172 goto error_open;
4173 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304174 } else {
4175 /* primary path is the default path selected if no other outputs are available/suitable */
4176 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4177 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4178 }
4179 out->hal_ip_format = format = out->format;
4180 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4181 out->hal_op_format = pcm_format_to_hal(out->config.format);
4182 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4183 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004184 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304185 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304186 if (out->hal_ip_format != out->hal_op_format) {
4187 uint32_t buffer_size = out->config.period_size *
4188 format_to_bitwidth_table[out->hal_op_format] *
4189 out->config.channels;
4190 out->convert_buffer = calloc(1, buffer_size);
4191 if (out->convert_buffer == NULL){
4192 ALOGE("Allocation failed for convert buffer for size %d",
4193 out->compr_config.fragment_size);
4194 ret = -ENOMEM;
4195 goto error_open;
4196 }
4197 ALOGD("Convert buffer allocated of size %d", buffer_size);
4198 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199 }
4200
Ashish Jain83a6cc22016-06-28 14:34:17 +05304201 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4202 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4203
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004204 /* TODO remove this hardcoding and check why width is zero*/
4205 if (out->bit_width == 0)
4206 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304207 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004208 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304209 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304210 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304211 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004212 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4213 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4214 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004215 if(adev->primary_output == NULL)
4216 adev->primary_output = out;
4217 else {
4218 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004219 ret = -EEXIST;
4220 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004221 }
4222 }
4223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224 /* Check if this usecase is already existing */
4225 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004226 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4227 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004230 ret = -EEXIST;
4231 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232 }
4233 pthread_mutex_unlock(&adev->lock);
4234
4235 out->stream.common.get_sample_rate = out_get_sample_rate;
4236 out->stream.common.set_sample_rate = out_set_sample_rate;
4237 out->stream.common.get_buffer_size = out_get_buffer_size;
4238 out->stream.common.get_channels = out_get_channels;
4239 out->stream.common.get_format = out_get_format;
4240 out->stream.common.set_format = out_set_format;
4241 out->stream.common.standby = out_standby;
4242 out->stream.common.dump = out_dump;
4243 out->stream.common.set_parameters = out_set_parameters;
4244 out->stream.common.get_parameters = out_get_parameters;
4245 out->stream.common.add_audio_effect = out_add_audio_effect;
4246 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4247 out->stream.get_latency = out_get_latency;
4248 out->stream.set_volume = out_set_volume;
4249 out->stream.write = out_write;
4250 out->stream.get_render_position = out_get_render_position;
4251 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004252 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004254 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004256 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004257 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258
4259 config->format = out->stream.common.get_format(&out->stream.common);
4260 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4261 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4262
4263 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304264 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004265 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004266
4267 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4268 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4269 popcount(out->channel_mask), out->playback_started);
4270
Eric Laurent994a6932013-07-17 11:51:42 -07004271 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004273
4274error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304275 if (out->convert_buffer)
4276 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004277 free(out);
4278 *stream_out = NULL;
4279 ALOGD("%s: exit: ret %d", __func__, ret);
4280 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281}
4282
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304283void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284 struct audio_stream_out *stream)
4285{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004286 struct stream_out *out = (struct stream_out *)stream;
4287 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004288 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004289
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304290 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4291
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004292 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304293 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004294 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304295 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004296 if(ret != 0)
4297 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4298 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004299 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004300 out_standby(&stream->common);
4301
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004302 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004303 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004304 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004305 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004306 if (out->compr_config.codec != NULL)
4307 free(out->compr_config.codec);
4308 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004309
Ashish Jain83a6cc22016-06-28 14:34:17 +05304310 if (out->convert_buffer != NULL) {
4311 free(out->convert_buffer);
4312 out->convert_buffer = NULL;
4313 }
4314
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004315 if (adev->voice_tx_output == out)
4316 adev->voice_tx_output = NULL;
4317
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304318 if (adev->primary_output == out)
4319 adev->primary_output = NULL;
4320
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004321 pthread_cond_destroy(&out->cond);
4322 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004324 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325}
4326
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004327static void close_compress_sessions(struct audio_device *adev)
4328{
Mingming Yin7b762e72015-03-04 13:47:32 -08004329 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304330 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004331 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004332 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304333
4334 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004335 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304336 if (is_offload_usecase(usecase->id)) {
4337 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004338 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4339 out = usecase->stream.out;
4340 pthread_mutex_unlock(&adev->lock);
4341 out_standby(&out->stream.common);
4342 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004343 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004344 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304345 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004346 }
4347 pthread_mutex_unlock(&adev->lock);
4348}
4349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4351{
4352 struct audio_device *adev = (struct audio_device *)dev;
4353 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004355 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004356 int ret;
4357 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004359 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304362 if (!parms)
4363 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004364 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4365 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304366 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304367 if (strstr(snd_card_status, "OFFLINE")) {
4368 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304369 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004370 //close compress sessions on OFFLINE status
4371 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304372 } else if (strstr(snd_card_status, "ONLINE")) {
4373 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304374 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004375 //send dts hpx license if enabled
4376 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304377 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304378 }
4379
4380 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004381 status = voice_set_parameters(adev, parms);
4382 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004383 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004385 status = platform_set_parameters(adev->platform, parms);
4386 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004387 goto done;
4388
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004389 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4390 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004391 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4393 adev->bluetooth_nrec = true;
4394 else
4395 adev->bluetooth_nrec = false;
4396 }
4397
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004398 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4399 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4401 adev->screen_off = false;
4402 else
4403 adev->screen_off = true;
4404 }
4405
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004406 ret = str_parms_get_int(parms, "rotation", &val);
4407 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004408 bool reverse_speakers = false;
4409 switch(val) {
4410 // FIXME: note that the code below assumes that the speakers are in the correct placement
4411 // relative to the user when the device is rotated 90deg from its default rotation. This
4412 // assumption is device-specific, not platform-specific like this code.
4413 case 270:
4414 reverse_speakers = true;
4415 break;
4416 case 0:
4417 case 90:
4418 case 180:
4419 break;
4420 default:
4421 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004422 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004423 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004424 if (status == 0) {
4425 if (adev->speaker_lr_swap != reverse_speakers) {
4426 adev->speaker_lr_swap = reverse_speakers;
4427 // only update the selected device if there is active pcm playback
4428 struct audio_usecase *usecase;
4429 struct listnode *node;
4430 list_for_each(node, &adev->usecase_list) {
4431 usecase = node_to_item(node, struct audio_usecase, list);
4432 if (usecase->type == PCM_PLAYBACK) {
4433 select_devices(adev, usecase->id);
4434 break;
4435 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004436 }
4437 }
4438 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004439 }
4440
Mingming Yin514a8bc2014-07-29 15:22:21 -07004441 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4442 if (ret >= 0) {
4443 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4444 adev->bt_wb_speech_enabled = true;
4445 else
4446 adev->bt_wb_speech_enabled = false;
4447 }
4448
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004449 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4450 if (ret >= 0) {
4451 val = atoi(value);
4452 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004453 ALOGV("cache new ext disp type and edid");
4454 ret = platform_get_ext_disp_type(adev->platform);
4455 if (ret < 0) {
4456 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004457 status = ret;
4458 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004459 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004460 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004461 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004462 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004463 /*
4464 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4465 * Per AudioPolicyManager, USB device is higher priority than WFD.
4466 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4467 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4468 * starting voice call on USB
4469 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004470 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4471 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004472 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4473 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004474 }
vivek mehta344576a2016-04-12 18:56:03 -07004475 ALOGV("detected USB connect .. disable proxy");
4476 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004477 }
4478 }
4479
4480 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4481 if (ret >= 0) {
4482 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004483 /*
4484 * The HDMI / Displayport disconnect handling has been moved to
4485 * audio extension to ensure that its parameters are not
4486 * invalidated prior to updating sysfs of the disconnect event
4487 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4488 */
4489 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004490 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004491 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4492 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304493 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4494 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004495 }
vivek mehta344576a2016-04-12 18:56:03 -07004496 ALOGV("detected USB disconnect .. enable proxy");
4497 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004498 }
4499 }
4500
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304501 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4502 if (ret >= 0) {
4503 struct audio_usecase *usecase;
4504 struct listnode *node;
4505 list_for_each(node, &adev->usecase_list) {
4506 usecase = node_to_item(node, struct audio_usecase, list);
4507 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004508 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304509 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304510 lock_output_stream(usecase->stream.out);
4511 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304512 //force device switch to re configure encoder
4513 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304514 audio_extn_a2dp_set_handoff_mode(false);
4515 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304516 break;
4517 }
4518 }
4519 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304520 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004521done:
4522 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004523 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304524error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004525 ALOGV("%s: exit with code(%d)", __func__, status);
4526 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527}
4528
4529static char* adev_get_parameters(const struct audio_hw_device *dev,
4530 const char *keys)
4531{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004532 struct audio_device *adev = (struct audio_device *)dev;
4533 struct str_parms *reply = str_parms_create();
4534 struct str_parms *query = str_parms_create_str(keys);
4535 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304536 char value[256] = {0};
4537 int ret = 0;
4538
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004539 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004540 if (reply) {
4541 str_parms_destroy(reply);
4542 }
4543 if (query) {
4544 str_parms_destroy(query);
4545 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004546 ALOGE("adev_get_parameters: failed to create query or reply");
4547 return NULL;
4548 }
4549
Naresh Tannirud7205b62014-06-20 02:54:48 +05304550 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4551 sizeof(value));
4552 if (ret >=0) {
4553 int val = 1;
4554 pthread_mutex_lock(&adev->snd_card_status.lock);
4555 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4556 val = 0;
4557 pthread_mutex_unlock(&adev->snd_card_status.lock);
4558 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4559 goto exit;
4560 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004561
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004562 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004563 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004564 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004565 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304566 pthread_mutex_unlock(&adev->lock);
4567
Naresh Tannirud7205b62014-06-20 02:54:48 +05304568exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004569 str = str_parms_to_str(reply);
4570 str_parms_destroy(query);
4571 str_parms_destroy(reply);
4572
4573 ALOGV("%s: exit: returns - %s", __func__, str);
4574 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575}
4576
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004577static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578{
4579 return 0;
4580}
4581
4582static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4583{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004584 int ret;
4585 struct audio_device *adev = (struct audio_device *)dev;
4586 pthread_mutex_lock(&adev->lock);
4587 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004588 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004589 pthread_mutex_unlock(&adev->lock);
4590 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591}
4592
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004593static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4594 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595{
4596 return -ENOSYS;
4597}
4598
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004599static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4600 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601{
4602 return -ENOSYS;
4603}
4604
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004605static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4606 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607{
4608 return -ENOSYS;
4609}
4610
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004611static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4612 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613{
4614 return -ENOSYS;
4615}
4616
4617static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4618{
4619 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621 pthread_mutex_lock(&adev->lock);
4622 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004623 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004625 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004626 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004627 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004628 adev->current_call_output = NULL;
4629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630 }
4631 pthread_mutex_unlock(&adev->lock);
4632 return 0;
4633}
4634
4635static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4636{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004637 int ret;
4638
4639 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004640 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004641 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4642 pthread_mutex_unlock(&adev->lock);
4643
4644 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645}
4646
4647static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4648{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004649 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 return 0;
4651}
4652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004653static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 const struct audio_config *config)
4655{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004656 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004658 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4659 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660}
4661
4662static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004663 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 audio_devices_t devices,
4665 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004666 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304667 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004668 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004669 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670{
4671 struct audio_device *adev = (struct audio_device *)dev;
4672 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004673 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004674 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004675 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304676 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304679 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4680 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304682 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683
4684 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004685
4686 if (!in) {
4687 ALOGE("failed to allocate input stream");
4688 return -ENOMEM;
4689 }
4690
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304691 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304692 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4693 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004694 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004695 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 in->stream.common.get_sample_rate = in_get_sample_rate;
4698 in->stream.common.set_sample_rate = in_set_sample_rate;
4699 in->stream.common.get_buffer_size = in_get_buffer_size;
4700 in->stream.common.get_channels = in_get_channels;
4701 in->stream.common.get_format = in_get_format;
4702 in->stream.common.set_format = in_set_format;
4703 in->stream.common.standby = in_standby;
4704 in->stream.common.dump = in_dump;
4705 in->stream.common.set_parameters = in_set_parameters;
4706 in->stream.common.get_parameters = in_get_parameters;
4707 in->stream.common.add_audio_effect = in_add_audio_effect;
4708 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4709 in->stream.set_gain = in_set_gain;
4710 in->stream.read = in_read;
4711 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4712
4713 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004714 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004715 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716 in->standby = 1;
4717 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004718 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004719 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004720
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304721 in->usecase = USECASE_AUDIO_RECORD;
4722 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4723 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4724 is_low_latency = true;
4725#if LOW_LATENCY_CAPTURE_USE_CASE
4726 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4727#endif
4728 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4729 }
4730
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004731 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004732 if (in->realtime) {
4733 in->config = pcm_config_audio_capture_rt;
4734 in->sample_rate = in->config.rate;
4735 in->af_period_multiplier = af_period_multiplier;
4736 } else {
4737 in->config = pcm_config_audio_capture;
4738 in->config.rate = config->sample_rate;
4739 in->sample_rate = config->sample_rate;
4740 in->af_period_multiplier = 1;
4741 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304742 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004743
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304744 /* restrict 24 bit capture for unprocessed source only
4745 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4746 */
4747 if (config->format == AUDIO_FORMAT_DEFAULT) {
4748 config->format = AUDIO_FORMAT_PCM_16_BIT;
4749 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4750 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4751 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4752 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4753 bool ret_error = false;
4754 in->bit_width = 24;
4755 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4756 from HAL is 24_packed and 8_24
4757 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4758 24_packed return error indicating supported format is 24_packed
4759 *> In case of any other source requesting 24 bit or float return error
4760 indicating format supported is 16 bit only.
4761
4762 on error flinger will retry with supported format passed
4763 */
4764 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4765 (source != AUDIO_SOURCE_CAMCORDER)) {
4766 config->format = AUDIO_FORMAT_PCM_16_BIT;
4767 if (config->sample_rate > 48000)
4768 config->sample_rate = 48000;
4769 ret_error = true;
4770 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4771 in->config.format = PCM_FORMAT_S24_3LE;
4772 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4773 in->config.format = PCM_FORMAT_S24_LE;
4774 } else {
4775 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4776 ret_error = true;
4777 }
4778
4779 if (ret_error) {
4780 ret = -EINVAL;
4781 goto err_open;
4782 }
4783 }
4784
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304785 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304786 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4787 (adev->mode != AUDIO_MODE_IN_CALL)) {
4788 ret = -EINVAL;
4789 goto err_open;
4790 }
4791
4792 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4793 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004794 if (config->sample_rate == 0)
4795 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4796 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4797 config->sample_rate != 8000) {
4798 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4799 ret = -EINVAL;
4800 goto err_open;
4801 }
4802 if (config->format == AUDIO_FORMAT_DEFAULT)
4803 config->format = AUDIO_FORMAT_PCM_16_BIT;
4804 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4805 config->format = AUDIO_FORMAT_PCM_16_BIT;
4806 ret = -EINVAL;
4807 goto err_open;
4808 }
4809
4810 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4811 in->config = pcm_config_afe_proxy_record;
4812 in->config.channels = channel_count;
4813 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304814 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304815 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4816 in, config, &channel_mask_updated)) {
4817 if (channel_mask_updated == true) {
4818 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4819 __func__, config->channel_mask);
4820 ret = -EINVAL;
4821 goto err_open;
4822 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304823 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004824 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004825 audio_extn_compr_cap_format_supported(config->format) &&
4826 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004827 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304828 } else if (audio_extn_cin_applicable_stream(in)) {
4829 ret = audio_extn_cin_configure_input_stream(in);
4830 if (ret)
4831 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004832 } else {
4833 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004834 if (!in->realtime) {
4835 in->format = config->format;
4836 frame_size = audio_stream_in_frame_size(&in->stream);
4837 buffer_size = get_input_buffer_size(config->sample_rate,
4838 config->format,
4839 channel_count,
4840 is_low_latency);
4841 in->config.period_size = buffer_size / frame_size;
4842 }
4843
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004844 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004845 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004846 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004847 (in->config.rate == 8000 || in->config.rate == 16000 ||
4848 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004849 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4850 voice_extn_compress_voip_open_input_stream(in);
4851 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004852 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304854 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4855 &adev->streams_input_cfg_list,
4856 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304857 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304858
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004859 /* This stream could be for sound trigger lab,
4860 get sound trigger pcm if present */
4861 audio_extn_sound_trigger_check_and_get_session(in);
4862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004864 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004865 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866
4867err_open:
4868 free(in);
4869 *stream_in = NULL;
4870 return ret;
4871}
4872
4873static void adev_close_input_stream(struct audio_hw_device *dev,
4874 struct audio_stream_in *stream)
4875{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004876 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004877 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004878 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304879
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304880 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004881
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304882 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004883 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304884
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004885 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304886 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004887 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304888 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004889 if (ret != 0)
4890 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4891 __func__, ret);
4892 } else
4893 in_standby(&stream->common);
4894
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004895 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004896 audio_extn_ssr_deinit();
4897 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304899 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004900 audio_extn_compr_cap_format_supported(in->config.format))
4901 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304902
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304903 if (audio_extn_cin_attached_usecase(in->usecase))
4904 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004905
Mingming Yinfd7607b2016-01-22 12:48:44 -08004906 if (in->is_st_session) {
4907 ALOGV("%s: sound trigger pcm stop lab", __func__);
4908 audio_extn_sound_trigger_stop_lab(in);
4909 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004910 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911 return;
4912}
4913
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004914static int adev_dump(const audio_hw_device_t *device __unused,
4915 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916{
4917 return 0;
4918}
4919
4920static int adev_close(hw_device_t *device)
4921{
4922 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004923
4924 if (!adev)
4925 return 0;
4926
4927 pthread_mutex_lock(&adev_init_lock);
4928
4929 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004930 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004931 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304932 audio_extn_utils_release_streams_cfg_lists(
4933 &adev->streams_output_cfg_list,
4934 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304935 if (audio_extn_qaf_is_enabled())
4936 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004937 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004938 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004939 free(adev->snd_dev_ref_cnt);
4940 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004941 if (adev->adm_deinit)
4942 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304943 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004944 free(device);
4945 adev = NULL;
4946 }
4947 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004949 return 0;
4950}
4951
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004952/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4953 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4954 * just that it _might_ work.
4955 */
4956static int period_size_is_plausible_for_low_latency(int period_size)
4957{
4958 switch (period_size) {
4959 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004960 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004961 case 240:
4962 case 320:
4963 case 480:
4964 return 1;
4965 default:
4966 return 0;
4967 }
4968}
4969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004970static int adev_open(const hw_module_t *module, const char *name,
4971 hw_device_t **device)
4972{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304973 int ret;
4974
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004975 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4977
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004978 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004979 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004980 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004981 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004982 ALOGD("%s: returning existing instance of adev", __func__);
4983 ALOGD("%s: exit", __func__);
4984 pthread_mutex_unlock(&adev_init_lock);
4985 return 0;
4986 }
4987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 adev = calloc(1, sizeof(struct audio_device));
4989
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004990 if (!adev) {
4991 pthread_mutex_unlock(&adev_init_lock);
4992 return -ENOMEM;
4993 }
4994
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004995 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4998 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4999 adev->device.common.module = (struct hw_module_t *)module;
5000 adev->device.common.close = adev_close;
5001
5002 adev->device.init_check = adev_init_check;
5003 adev->device.set_voice_volume = adev_set_voice_volume;
5004 adev->device.set_master_volume = adev_set_master_volume;
5005 adev->device.get_master_volume = adev_get_master_volume;
5006 adev->device.set_master_mute = adev_set_master_mute;
5007 adev->device.get_master_mute = adev_get_master_mute;
5008 adev->device.set_mode = adev_set_mode;
5009 adev->device.set_mic_mute = adev_set_mic_mute;
5010 adev->device.get_mic_mute = adev_get_mic_mute;
5011 adev->device.set_parameters = adev_set_parameters;
5012 adev->device.get_parameters = adev_get_parameters;
5013 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5014 adev->device.open_output_stream = adev_open_output_stream;
5015 adev->device.close_output_stream = adev_close_output_stream;
5016 adev->device.open_input_stream = adev_open_input_stream;
5017 adev->device.close_input_stream = adev_close_input_stream;
5018 adev->device.dump = adev_dump;
5019
5020 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005022 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005023 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005024 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005025 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005026 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005027 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005028 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005029 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005030 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005031 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005032 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005033 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305034 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305035 adev->perf_lock_opts[0] = 0x101;
5036 adev->perf_lock_opts[1] = 0x20E;
5037 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305038
5039 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5040 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005041 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005042 adev->platform = platform_init(adev);
5043 if (!adev->platform) {
5044 free(adev->snd_dev_ref_cnt);
5045 free(adev);
5046 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5047 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005048 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305049 pthread_mutex_destroy(&adev->lock);
5050 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005051 return -EINVAL;
5052 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005053
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305054 if (audio_extn_qaf_is_enabled()) {
5055 ret = audio_extn_qaf_init(adev);
5056 if (ret < 0) {
5057 free(adev);
5058 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5059 *device = NULL;
5060 pthread_mutex_unlock(&adev_init_lock);
5061 pthread_mutex_destroy(&adev->lock);
5062 return ret;
5063 }
5064
5065 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5066 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5067 }
5068
Naresh Tanniru4c630392014-05-12 01:05:52 +05305069 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5070
Eric Laurentc4aef752013-09-12 17:45:53 -07005071 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5072 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5073 if (adev->visualizer_lib == NULL) {
5074 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5075 } else {
5076 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5077 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005078 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005079 "visualizer_hal_start_output");
5080 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005081 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005082 "visualizer_hal_stop_output");
5083 }
5084 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305085 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005086 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005087 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005088 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005089
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005090 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5091 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5092 if (adev->offload_effects_lib == NULL) {
5093 ALOGE("%s: DLOPEN failed for %s", __func__,
5094 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5095 } else {
5096 ALOGV("%s: DLOPEN successful for %s", __func__,
5097 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5098 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305099 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005100 "offload_effects_bundle_hal_start_output");
5101 adev->offload_effects_stop_output =
5102 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5103 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005104 adev->offload_effects_set_hpx_state =
5105 (int (*)(bool))dlsym(adev->offload_effects_lib,
5106 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305107 adev->offload_effects_get_parameters =
5108 (void (*)(struct str_parms *, struct str_parms *))
5109 dlsym(adev->offload_effects_lib,
5110 "offload_effects_bundle_get_parameters");
5111 adev->offload_effects_set_parameters =
5112 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5113 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005114 }
5115 }
5116
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005117 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5118 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5119 if (adev->adm_lib == NULL) {
5120 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5121 } else {
5122 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5123 adev->adm_init = (adm_init_t)
5124 dlsym(adev->adm_lib, "adm_init");
5125 adev->adm_deinit = (adm_deinit_t)
5126 dlsym(adev->adm_lib, "adm_deinit");
5127 adev->adm_register_input_stream = (adm_register_input_stream_t)
5128 dlsym(adev->adm_lib, "adm_register_input_stream");
5129 adev->adm_register_output_stream = (adm_register_output_stream_t)
5130 dlsym(adev->adm_lib, "adm_register_output_stream");
5131 adev->adm_deregister_stream = (adm_deregister_stream_t)
5132 dlsym(adev->adm_lib, "adm_deregister_stream");
5133 adev->adm_request_focus = (adm_request_focus_t)
5134 dlsym(adev->adm_lib, "adm_request_focus");
5135 adev->adm_abandon_focus = (adm_abandon_focus_t)
5136 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005137 adev->adm_set_config = (adm_set_config_t)
5138 dlsym(adev->adm_lib, "adm_set_config");
5139 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5140 dlsym(adev->adm_lib, "adm_request_focus_v2");
5141 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5142 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5143 adev->adm_on_routing_change = (adm_on_routing_change_t)
5144 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005145 }
5146 }
5147
Mingming Yin514a8bc2014-07-29 15:22:21 -07005148 adev->bt_wb_speech_enabled = false;
5149
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005150 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151 *device = &adev->device.common;
5152
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305153 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5154 &adev->streams_output_cfg_list,
5155 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005156
Kiran Kandi910e1862013-10-29 13:29:42 -07005157 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005158
5159 char value[PROPERTY_VALUE_MAX];
5160 int trial;
5161 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5162 trial = atoi(value);
5163 if (period_size_is_plausible_for_low_latency(trial)) {
5164 pcm_config_low_latency.period_size = trial;
5165 pcm_config_low_latency.start_threshold = trial / 4;
5166 pcm_config_low_latency.avail_min = trial / 4;
5167 configured_low_latency_capture_period_size = trial;
5168 }
5169 }
5170 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5171 trial = atoi(value);
5172 if (period_size_is_plausible_for_low_latency(trial)) {
5173 configured_low_latency_capture_period_size = trial;
5174 }
5175 }
5176
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005177 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5178 af_period_multiplier = atoi(value);
5179 if (af_period_multiplier < 0)
5180 af_period_multiplier = 2;
5181 else if (af_period_multiplier > 4)
5182 af_period_multiplier = 4;
5183
5184 ALOGV("new period_multiplier = %d", af_period_multiplier);
5185 }
5186
vivek mehta446c3962015-09-14 10:57:35 -07005187 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005188 pthread_mutex_unlock(&adev_init_lock);
5189
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005190 if (adev->adm_init)
5191 adev->adm_data = adev->adm_init();
5192
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305193 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305194 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005195 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005196 return 0;
5197}
5198
5199static struct hw_module_methods_t hal_module_methods = {
5200 .open = adev_open,
5201};
5202
5203struct audio_module HAL_MODULE_INFO_SYM = {
5204 .common = {
5205 .tag = HARDWARE_MODULE_TAG,
5206 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5207 .hal_api_version = HARDWARE_HAL_API_VERSION,
5208 .id = AUDIO_HARDWARE_MODULE_ID,
5209 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005210 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 .methods = &hal_module_methods,
5212 },
5213};