blob: 595e72b601c76b67e592db6443382fe4f880ebef [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082/* ToDo: Check and update a proper value in msec */
Alexy Joseph01e54e62015-03-03 19:01:03 -080083#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053085#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070086
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070087#define PROXY_OPEN_RETRY_COUNT 100
88#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080089
Mingming Yin08c7e312015-03-16 18:10:58 -070090#ifdef USE_LL_AS_PRIMARY_OUTPUT
91#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
92#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
93#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080094#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070095#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
96#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080097
Haynes Mathew George5beddd42016-06-27 18:33:40 -070098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurentb23d5282013-05-14 15:27:20 -0700103struct pcm_config pcm_config_deep_buffer = {
104 .channels = 2,
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
106 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
107 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110 .stop_threshold = INT_MAX,
111 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
112};
113
114struct pcm_config pcm_config_low_latency = {
115 .channels = 2,
116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
118 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
123};
124
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700125static int af_period_multiplier = 4;
126struct pcm_config pcm_config_rt = {
127 .channels = 2,
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
129 .period_size = ULL_PERIOD_SIZE, //1 ms
130 .period_count = 512, //=> buffer size is 512ms
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
133 .stop_threshold = INT_MAX,
134 .silence_threshold = 0,
135 .silence_size = 0,
136 .avail_min = ULL_PERIOD_SIZE, //1 ms
137};
138
Eric Laurentb23d5282013-05-14 15:27:20 -0700139struct pcm_config pcm_config_hdmi_multi = {
140 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
141 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
142 .period_size = HDMI_MULTI_PERIOD_SIZE,
143 .period_count = HDMI_MULTI_PERIOD_COUNT,
144 .format = PCM_FORMAT_S16_LE,
145 .start_threshold = 0,
146 .stop_threshold = INT_MAX,
147 .avail_min = 0,
148};
149
150struct pcm_config pcm_config_audio_capture = {
151 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154};
155
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700156struct pcm_config pcm_config_audio_capture_rt = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = ULL_PERIOD_SIZE,
160 .period_count = 512,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = 0,
163 .stop_threshold = INT_MAX,
164 .silence_threshold = 0,
165 .silence_size = 0,
166 .avail_min = ULL_PERIOD_SIZE, //1 ms
167};
168
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700169#define AFE_PROXY_CHANNEL_COUNT 2
170#define AFE_PROXY_SAMPLING_RATE 48000
171
172#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
173#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
174
175struct pcm_config pcm_config_afe_proxy_playback = {
176 .channels = AFE_PROXY_CHANNEL_COUNT,
177 .rate = AFE_PROXY_SAMPLING_RATE,
178 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
179 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
180 .format = PCM_FORMAT_S16_LE,
181 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182 .stop_threshold = INT_MAX,
183 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
184};
185
186#define AFE_PROXY_RECORD_PERIOD_SIZE 768
187#define AFE_PROXY_RECORD_PERIOD_COUNT 4
188
189struct pcm_config pcm_config_afe_proxy_record = {
190 .channels = AFE_PROXY_CHANNEL_COUNT,
191 .rate = AFE_PROXY_SAMPLING_RATE,
192 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
193 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
198};
199
Ashish Jainf1eaa582016-05-23 20:54:24 +0530200#define AUDIO_MAX_PCM_FORMATS 7
201
202const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
203 [AUDIO_FORMAT_DEFAULT] = 0,
204 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
205 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
206 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
208 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
209 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
210};
211
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800212const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700213 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
214 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700215 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
216 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700218 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700219 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700227
Eric Laurentb23d5282013-05-14 15:27:20 -0700228 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700229 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530230 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
231 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
232 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700233 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700234 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700235 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800236 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800237 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700239
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700240 [USECASE_VOICE2_CALL] = "voice2-call",
241 [USECASE_VOLTE_CALL] = "volte-call",
242 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800243 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800244 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
245 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800246 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700247 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
248 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
249 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800250 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
251 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
252 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
253
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700254 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
255 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700256 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
257 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700258
259 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
260 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700261 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700262};
263
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264static const audio_usecase_t offload_usecases[] = {
265 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700266 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700274};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800275
276#define STRING_TO_ENUM(string) { #string, string }
277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800278struct string_to_enum {
279 const char *name;
280 uint32_t value;
281};
282
283static const struct string_to_enum out_channels_name_to_enum_table[] = {
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
292};
293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700294static const struct string_to_enum out_formats_name_to_enum_table[] = {
295 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
296 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
297 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800298 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
299 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
300};
301
302//list of all supported sample rates by HDMI specification.
303static const int out_hdmi_sample_rates[] = {
304 32000, 44100, 48000, 88200, 96000, 176400, 192000,
305};
306
307static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
308 STRING_TO_ENUM(32000),
309 STRING_TO_ENUM(44100),
310 STRING_TO_ENUM(48000),
311 STRING_TO_ENUM(88200),
312 STRING_TO_ENUM(96000),
313 STRING_TO_ENUM(176400),
314 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700315};
316
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700317static struct audio_device *adev = NULL;
318static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700319static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700322
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (is_offload_usecase(out->usecase) ||
348 !adev->adm_register_output_stream)
349 return;
350
351 // register stream first for backward compatibility
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime)
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime)
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383}
384
385static void request_out_focus(struct stream_out *out, long ns)
386{
387 struct audio_device *adev = out->dev;
388
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700389 if (adev->adm_request_focus_v2)
390 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
391 else if (adev->adm_request_focus)
392 adev->adm_request_focus(adev->adm_data, out->handle);
393}
394
395static void request_in_focus(struct stream_in *in, long ns)
396{
397 struct audio_device *adev = in->dev;
398
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700399 if (adev->adm_request_focus_v2)
400 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
401 else if (adev->adm_request_focus)
402 adev->adm_request_focus(adev->adm_data, in->capture_handle);
403}
404
405static void release_out_focus(struct stream_out *out)
406{
407 struct audio_device *adev = out->dev;
408
409 if (adev->adm_abandon_focus)
410 adev->adm_abandon_focus(adev->adm_data, out->handle);
411}
412
413static void release_in_focus(struct stream_in *in)
414{
415 struct audio_device *adev = in->dev;
416 if (adev->adm_abandon_focus)
417 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
418}
419
vivek mehtaa76401a2015-04-24 14:12:15 -0700420__attribute__ ((visibility ("default")))
421bool audio_hw_send_gain_dep_calibration(int level) {
422 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700423 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700424
425 pthread_mutex_lock(&adev_init_lock);
426
427 if (adev != NULL && adev->platform != NULL) {
428 pthread_mutex_lock(&adev->lock);
429 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700430
431 // if cal set fails, cache level info
432 // if cal set succeds, reset known last cal set
433 if (!ret_val)
434 last_known_cal_step = level;
435 else if (last_known_cal_step != -1)
436 last_known_cal_step = -1;
437
vivek mehtaa76401a2015-04-24 14:12:15 -0700438 pthread_mutex_unlock(&adev->lock);
439 } else {
440 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
441 }
442
443 pthread_mutex_unlock(&adev_init_lock);
444
445 return ret_val;
446}
447
Ashish Jain5106d362016-05-11 19:23:33 +0530448static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
449{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800450 bool gapless_enabled = false;
451 const char *mixer_ctl_name = "Compress Gapless Playback";
452 struct mixer_ctl *ctl;
453
454 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530455 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
456
457 /*Disable gapless if its AV playback*/
458 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800459
460 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
461 if (!ctl) {
462 ALOGE("%s: Could not get ctl for mixer cmd - %s",
463 __func__, mixer_ctl_name);
464 return -EINVAL;
465 }
466
467 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
468 ALOGE("%s: Could not set gapless mode %d",
469 __func__, gapless_enabled);
470 return -EINVAL;
471 }
472 return 0;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent86e17132013-09-12 17:49:30 -0700498 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530499 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530500 format == AUDIO_FORMAT_AAC_LC ||
501 format == AUDIO_FORMAT_AAC_HE_V1 ||
502 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530503 format == AUDIO_FORMAT_AAC_ADTS_LC ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
505 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530506 format == AUDIO_FORMAT_AAC_LATM_LC ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530509 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
510 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530511 format == AUDIO_FORMAT_PCM_FLOAT ||
512 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700513 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530514 format == AUDIO_FORMAT_AC3 ||
515 format == AUDIO_FORMAT_E_AC3 ||
516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530524 format == AUDIO_FORMAT_WMA_PRO ||
525 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800526 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700527
528 return false;
529}
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static inline bool is_mmap_usecase(audio_usecase_t uc_id)
532{
533 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
534 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
535}
536
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530537int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530538{
539 int snd_scard_state;
540
541 if (!adev)
542 return SND_CARD_STATE_OFFLINE;
543
544 pthread_mutex_lock(&adev->snd_card_status.lock);
545 snd_scard_state = adev->snd_card_status.state;
546 pthread_mutex_unlock(&adev->snd_card_status.lock);
547
548 return snd_scard_state;
549}
550
551static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
552{
553 if (!adev)
554 return -ENOSYS;
555
556 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700557 if (adev->snd_card_status.state != snd_scard_state) {
558 adev->snd_card_status.state = snd_scard_state;
559 platform_snd_card_update(adev->platform, snd_scard_state);
560 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530561 pthread_mutex_unlock(&adev->snd_card_status.lock);
562
563 return 0;
564}
565
Avinash Vaish71a8b972014-07-24 15:36:33 +0530566static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
567 struct audio_usecase *uc_info)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571
572 if (uc_info == NULL)
573 return -EINVAL;
574
575 /* Re-route all voice usecases on the shared backend other than the
576 specified usecase to new snd devices */
577 list_for_each(node, &adev->usecase_list) {
578 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800579 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530580 enable_audio_route(adev, usecase);
581 }
582 return 0;
583}
584
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530586{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530587 ALOGV("%s", __func__);
588 audio_route_apply_and_update_path(adev->audio_route,
589 "asrc-mode");
590 adev->asrc_mode_enabled = true;
591}
592
593static void disable_asrc_mode(struct audio_device *adev)
594{
595 ALOGV("%s", __func__);
596 audio_route_reset_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = false;
599}
600
601/*
602 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
603 * 44.1 or Native DSD backends are enabled for any of current use case.
604 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
605 * - Disable current mix path use case(Headphone backend) and re-enable it with
606 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
607 * e.g. Naitve DSD or Headphone 44.1 -> + 48
608 */
609static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
610{
611 ALOGV("%s snd device %d", __func__, snd_device);
612 int new_backend_idx = platform_get_backend_index(snd_device);
613
614 if (((new_backend_idx == HEADPHONE_BACKEND) ||
615 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
616 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
617 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530618 struct listnode *node = NULL;
619 struct audio_usecase *uc = NULL;
620 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530621 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Garmond Leung50058f62017-02-08 09:49:30 -0800622 int i, num_devices, ret = 0;
623 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530624
625 list_for_each(node, &adev->usecase_list) {
626 uc = node_to_item(node, struct audio_usecase, list);
627 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530628
Garmond Leung50058f62017-02-08 09:49:30 -0800629 if (curr_out && PCM_PLAYBACK == uc->type) {
630 ret = platform_split_snd_device(adev->platform,
631 uc->out_snd_device,
632 &num_devices,
633 split_snd_devices);
634 if (ret < 0 || num_devices == 0) {
635 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
636 split_snd_devices[0] = uc->out_snd_device;
637 num_devices = 1;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530638 }
Garmond Leung50058f62017-02-08 09:49:30 -0800639 for (i = 0; i < num_devices; i++) {
640 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
641 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
642 if((new_backend_idx == HEADPHONE_BACKEND) &&
643 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
644 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
645 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
646 __func__);
647 enable_asrc_mode(adev);
648 break;
649 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
650 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
651 (usecase_backend_idx == HEADPHONE_BACKEND)) {
652 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
653 __func__);
654 disable_audio_route(adev, uc);
655 disable_snd_device(adev, uc->out_snd_device);
656 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
657 if (new_backend_idx == DSD_NATIVE_BACKEND)
658 audio_route_apply_and_update_path(adev->audio_route,
659 "hph-true-highquality-mode");
660 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
661 (curr_out->bit_width >= 24))
662 audio_route_apply_and_update_path(adev->audio_route,
663 "hph-highquality-mode");
664 enable_asrc_mode(adev);
665 enable_snd_device(adev, uc->out_snd_device);
666 enable_audio_route(adev, uc);
667 break;
668 }
669 }
670 // reset split devices count
671 num_devices = 0;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530672 }
Garmond Leung50058f62017-02-08 09:49:30 -0800673 if (adev->asrc_mode_enabled)
674 break;
675
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530676 }
677 }
678}
679
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700680int pcm_ioctl(struct pcm *pcm, int request, ...)
681{
682 va_list ap;
683 void * arg;
684 int pcm_fd = *(int*)pcm;
685
686 va_start(ap, request);
687 arg = va_arg(ap, void *);
688 va_end(ap);
689
690 return ioctl(pcm_fd, request, arg);
691}
692
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700693int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700694 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800695{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700696 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700697 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800698
699 if (usecase == NULL)
700 return -EINVAL;
701
702 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
703
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800704 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800708
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800709#ifdef DS1_DOLBY_DAP_ENABLED
710 audio_extn_dolby_set_dmid(adev);
711 audio_extn_dolby_set_endpoint(adev);
712#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700713 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700714 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530715 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700716 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530717 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800718 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700719 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700720 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700721 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 ALOGV("%s: exit", __func__);
723 return 0;
724}
725
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700726int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700727 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800728{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700730 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800731
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530732 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800733 return -EINVAL;
734
735 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700736 if (usecase->type == PCM_CAPTURE)
737 snd_device = usecase->in_snd_device;
738 else
739 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800740 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700741 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700742 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700743 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700744 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530745 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746 ALOGV("%s: exit", __func__);
747 return 0;
748}
749
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700750int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700751 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530753 int i, num_devices = 0;
754 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700755 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
756
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800757 if (snd_device < SND_DEVICE_MIN ||
758 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800759 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800760 return -EINVAL;
761 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762
763 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700764
765 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
766 ALOGE("%s: Invalid sound device returned", __func__);
767 return -EINVAL;
768 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700769 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700770 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700771 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700772 return 0;
773 }
774
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530775
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700776 if (audio_extn_spkr_prot_is_enabled())
777 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700778
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800779 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
780 audio_extn_spkr_prot_is_enabled()) {
781 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700782 adev->snd_dev_ref_cnt[snd_device]--;
783 return -EINVAL;
784 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200785 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800786 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800787 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200788 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800789 return -EINVAL;
790 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700791 } else if (platform_split_snd_device(adev->platform,
792 snd_device,
793 &num_devices,
794 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530795 for (i = 0; i < num_devices; i++) {
796 enable_snd_device(adev, new_snd_devices[i]);
797 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800798 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700799 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530800
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530801 if (platform_check_codec_asrc_support(adev->platform))
802 check_and_set_asrc_mode(adev, snd_device);
803
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530804 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
805 (audio_extn_a2dp_start_playback() < 0)) {
806 ALOGE(" fail to configure A2dp control path ");
807 return -EINVAL;
808 }
809
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700810 /* due to the possibility of calibration overwrite between listen
811 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700812 audio_extn_sound_trigger_update_device_status(snd_device,
813 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530814 audio_extn_listen_update_device_status(snd_device,
815 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700816 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700817 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700818 audio_extn_sound_trigger_update_device_status(snd_device,
819 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530820 audio_extn_listen_update_device_status(snd_device,
821 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700822 return -EINVAL;
823 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300824 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700825 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530826
827 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
828 !adev->native_playback_enabled &&
829 audio_is_true_native_stream_active(adev)) {
830 ALOGD("%s: %d: napb: enabling native mode in hardware",
831 __func__, __LINE__);
832 audio_route_apply_and_update_path(adev->audio_route,
833 "true-native-mode");
834 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837 return 0;
838}
839
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700840int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700841 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530843 int i, num_devices = 0;
844 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700845 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
846
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800847 if (snd_device < SND_DEVICE_MIN ||
848 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800849 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800850 return -EINVAL;
851 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700852 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
853 ALOGE("%s: device ref cnt is already 0", __func__);
854 return -EINVAL;
855 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700858
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700859 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
860 ALOGE("%s: Invalid sound device returned", __func__);
861 return -EINVAL;
862 }
863
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700865 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530866
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800867 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
868 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700869 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700870 } else if (platform_split_snd_device(adev->platform,
871 snd_device,
872 &num_devices,
873 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530874 for (i = 0; i < num_devices; i++) {
875 disable_snd_device(adev, new_snd_devices[i]);
876 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300877 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700878 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300879 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700880
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530881 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
882 audio_extn_a2dp_stop_playback();
883
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700884 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530885 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530886 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
887 adev->native_playback_enabled) {
888 ALOGD("%s: %d: napb: disabling native mode in hardware",
889 __func__, __LINE__);
890 audio_route_reset_and_update_path(adev->audio_route,
891 "true-native-mode");
892 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530893 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
894 adev->asrc_mode_enabled) {
895 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530896 disable_asrc_mode(adev);
897 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530898 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530899
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200900 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700901 audio_extn_sound_trigger_update_device_status(snd_device,
902 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530903 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800904 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800907 return 0;
908}
909
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700910/*
911 legend:
912 uc - existing usecase
913 new_uc - new usecase
914 d1, d11, d2 - SND_DEVICE enums
915 a1, a2 - corresponding ANDROID device enums
916 B1, B2 - backend strings
917
918case 1
919 uc->dev d1 (a1) B1
920 new_uc->dev d1 (a1), d2 (a2) B1, B2
921
922 resolution: disable and enable uc->dev on d1
923
924case 2
925 uc->dev d1 (a1) B1
926 new_uc->dev d11 (a1) B1
927
928 resolution: need to switch uc since d1 and d11 are related
929 (e.g. speaker and voice-speaker)
930 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
931
932case 3
933 uc->dev d1 (a1) B1
934 new_uc->dev d2 (a2) B2
935
936 resolution: no need to switch uc
937
938case 4
939 uc->dev d1 (a1) B1
940 new_uc->dev d2 (a2) B1
941
942 resolution: disable enable uc-dev on d2 since backends match
943 we cannot enable two streams on two different devices if they
944 share the same backend. e.g. if offload is on speaker device using
945 QUAD_MI2S backend and a low-latency stream is started on voice-handset
946 using the same backend, offload must also be switched to voice-handset.
947
948case 5
949 uc->dev d1 (a1) B1
950 new_uc->dev d1 (a1), d2 (a2) B1
951
952 resolution: disable enable uc-dev on d2 since backends match
953 we cannot enable two streams on two different devices if they
954 share the same backend.
955
956case 6
957 uc->dev d1 (a1) B1
958 new_uc->dev d2 (a1) B2
959
960 resolution: no need to switch
961
962case 7
963 uc->dev d1 (a1), d2 (a2) B1, B2
964 new_uc->dev d1 (a1) B1
965
966 resolution: no need to switch
967
968*/
969static snd_device_t derive_playback_snd_device(void * platform,
970 struct audio_usecase *uc,
971 struct audio_usecase *new_uc,
972 snd_device_t new_snd_device)
973{
974 audio_devices_t a1 = uc->stream.out->devices;
975 audio_devices_t a2 = new_uc->stream.out->devices;
976
977 snd_device_t d1 = uc->out_snd_device;
978 snd_device_t d2 = new_snd_device;
979
980 // Treat as a special case when a1 and a2 are not disjoint
981 if ((a1 != a2) && (a1 & a2)) {
982 snd_device_t d3[2];
983 int num_devices = 0;
984 int ret = platform_split_snd_device(platform,
985 popcount(a1) > 1 ? d1 : d2,
986 &num_devices,
987 d3);
988 if (ret < 0) {
989 if (ret != -ENOSYS) {
990 ALOGW("%s failed to split snd_device %d",
991 __func__,
992 popcount(a1) > 1 ? d1 : d2);
993 }
994 goto end;
995 }
996
997 // NB: case 7 is hypothetical and isn't a practical usecase yet.
998 // But if it does happen, we need to give priority to d2 if
999 // the combo devices active on the existing usecase share a backend.
1000 // This is because we cannot have a usecase active on a combo device
1001 // and a new usecase requests one device in this combo pair.
1002 if (platform_check_backends_match(d3[0], d3[1])) {
1003 return d2; // case 5
1004 } else {
1005 return d1; // case 1
1006 }
1007 } else {
1008 if (platform_check_backends_match(d1, d2)) {
1009 return d2; // case 2, 4
1010 } else {
1011 return d1; // case 6, 3
1012 }
1013 }
1014
1015end:
1016 return d2; // return whatever was calculated before.
1017}
1018
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301020 struct audio_usecase *uc_info,
1021 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022{
1023 struct listnode *node;
1024 struct audio_usecase *usecase;
1025 bool switch_device[AUDIO_USECASE_MAX];
1026 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001027 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301028 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001029 /*
1030 * This function is to make sure that all the usecases that are active on
1031 * the hardware codec backend are always routed to any one device that is
1032 * handled by the hardware codec.
1033 * For example, if low-latency and deep-buffer usecases are currently active
1034 * on speaker and out_set_parameters(headset) is received on low-latency
1035 * output, then we have to make sure deep-buffer is also switched to headset,
1036 * because of the limitation that both the devices cannot be enabled
1037 * at the same time as they share the same backend.
1038 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001039 /*
1040 * This call is to check if we need to force routing for a particular stream
1041 * If there is a backend configuration change for the device when a
1042 * new stream starts, then ADM needs to be closed and re-opened with the new
1043 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001044 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001045 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001046 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1047 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301048 /* For a2dp device reconfigure all active sessions
1049 * with new AFE encoder format based on a2dp state
1050 */
1051 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1052 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1053 audio_extn_a2dp_is_force_device_switch()) {
1054 force_routing = true;
1055 force_restart_session = true;
1056 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301057 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1058
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001060 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001061 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1063 switch_device[i] = false;
1064
1065 list_for_each(node, &adev->usecase_list) {
1066 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001067
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301068 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1069 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301070 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301071 platform_get_snd_device_name(usecase->out_snd_device),
1072 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001073 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301074 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001075 (derive_playback_snd_device(adev->platform,
1076 usecase, uc_info,
1077 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301078 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1079 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301080 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301081 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1082 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1083 ((force_restart_session) ||
1084 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301085
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301086 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1087 __func__, use_case_table[usecase->id],
1088 platform_get_snd_device_name(usecase->out_snd_device));
1089 disable_audio_route(adev, usecase);
1090 switch_device[usecase->id] = true;
1091 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 }
1093 }
1094
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301095 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1096 num_uc_to_switch);
1097
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001099 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001100
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301101 /* Make sure the previous devices to be disabled first and then enable the
1102 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001103 list_for_each(node, &adev->usecase_list) {
1104 usecase = node_to_item(node, struct audio_usecase, list);
1105 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001106 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 }
1108 }
1109
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001110 list_for_each(node, &adev->usecase_list) {
1111 usecase = node_to_item(node, struct audio_usecase, list);
1112 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001113 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001114 }
1115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 /* Re-route all the usecases on the shared backend other than the
1118 specified usecase to new snd devices */
1119 list_for_each(node, &adev->usecase_list) {
1120 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301121 /* Update the out_snd_device only before enabling the audio route */
1122 if (switch_device[usecase->id]) {
1123 usecase->out_snd_device = snd_device;
1124 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301125 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301126 use_case_table[usecase->id],
1127 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001128 /* Update voc calibration before enabling VoIP route */
1129 if (usecase->type == VOIP_CALL)
1130 status = platform_switch_voice_call_device_post(adev->platform,
1131 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001132 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301133 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 }
1136 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 }
1138}
1139
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301140static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001141 struct audio_usecase *uc_info,
1142 snd_device_t snd_device)
1143{
1144 struct listnode *node;
1145 struct audio_usecase *usecase;
1146 bool switch_device[AUDIO_USECASE_MAX];
1147 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301148 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001149 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001150
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301151 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1152 snd_device);
1153 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301154
1155 /*
1156 * Make sure out devices is checked against out codec backend device and
1157 * also in devices against in codec backend. Checking out device against in
1158 * codec backend or vice versa causes issues.
1159 */
1160 if (uc_info->type == PCM_CAPTURE)
1161 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001162 /*
1163 * This function is to make sure that all the active capture usecases
1164 * are always routed to the same input sound device.
1165 * For example, if audio-record and voice-call usecases are currently
1166 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1167 * is received for voice call then we have to make sure that audio-record
1168 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1169 * because of the limitation that two devices cannot be enabled
1170 * at the same time if they share the same backend.
1171 */
1172 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1173 switch_device[i] = false;
1174
1175 list_for_each(node, &adev->usecase_list) {
1176 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301177 /*
1178 * TODO: Enhance below condition to handle BT sco/USB multi recording
1179 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001180 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301182 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301183 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301184 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001185 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001186 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001187 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1188 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001189 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001190 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 switch_device[usecase->id] = true;
1192 num_uc_to_switch++;
1193 }
1194 }
1195
1196 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001197 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001198
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301199 /* Make sure the previous devices to be disabled first and then enable the
1200 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001201 list_for_each(node, &adev->usecase_list) {
1202 usecase = node_to_item(node, struct audio_usecase, list);
1203 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001204 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001205 }
1206 }
1207
1208 list_for_each(node, &adev->usecase_list) {
1209 usecase = node_to_item(node, struct audio_usecase, list);
1210 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001211 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 }
1213 }
1214
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215 /* Re-route all the usecases on the shared backend other than the
1216 specified usecase to new snd devices */
1217 list_for_each(node, &adev->usecase_list) {
1218 usecase = node_to_item(node, struct audio_usecase, list);
1219 /* Update the in_snd_device only before enabling the audio route */
1220 if (switch_device[usecase->id] ) {
1221 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001222 if (usecase->type != VOICE_CALL) {
1223 /* Update voc calibration before enabling VoIP route */
1224 if (usecase->type == VOIP_CALL)
1225 status = platform_switch_voice_call_device_post(adev->platform,
1226 usecase->out_snd_device,
1227 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301228 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001229 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 }
1231 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001232 }
1233}
1234
Mingming Yin3a941d42016-02-17 18:08:05 -08001235static void reset_hdmi_sink_caps(struct stream_out *out) {
1236 int i = 0;
1237
1238 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1239 out->supported_channel_masks[i] = 0;
1240 }
1241 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1242 out->supported_formats[i] = 0;
1243 }
1244 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1245 out->supported_sample_rates[i] = 0;
1246 }
1247}
1248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001250static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001251{
Mingming Yin3a941d42016-02-17 18:08:05 -08001252 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001253 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254
Mingming Yin3a941d42016-02-17 18:08:05 -08001255 reset_hdmi_sink_caps(out);
1256
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001257 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001258 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001259 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001260 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001261 }
1262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001265 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001266 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001267 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1268 case 6:
1269 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1270 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1271 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1272 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1273 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1274 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 break;
1276 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001277 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001278 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 break;
1280 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001281
1282 // check channel format caps
1283 i = 0;
1284 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1285 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1286 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1287 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1288 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1289 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1290 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1291 }
1292
1293 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1294 ALOGV(":%s HDMI supports DTS format", __func__);
1295 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1296 }
1297
1298 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1299 ALOGV(":%s HDMI supports DTS HD format", __func__);
1300 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1301 }
1302
1303
1304 // check sample rate caps
1305 i = 0;
1306 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1307 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1308 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1309 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1310 }
1311 }
1312
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001313 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314}
1315
Alexy Josephb1379942016-01-29 15:49:38 -08001316audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001317 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001318{
1319 struct audio_usecase *usecase;
1320 struct listnode *node;
1321
1322 list_for_each(node, &adev->usecase_list) {
1323 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001324 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001325 ALOGV("%s: usecase id %d", __func__, usecase->id);
1326 return usecase->id;
1327 }
1328 }
1329 return USECASE_INVALID;
1330}
1331
Alexy Josephb1379942016-01-29 15:49:38 -08001332struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001333 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334{
1335 struct audio_usecase *usecase;
1336 struct listnode *node;
1337
1338 list_for_each(node, &adev->usecase_list) {
1339 usecase = node_to_item(node, struct audio_usecase, list);
1340 if (usecase->id == uc_id)
1341 return usecase;
1342 }
1343 return NULL;
1344}
1345
Dhananjay Kumard4833242016-10-06 22:09:12 +05301346struct stream_in *get_next_active_input(const struct audio_device *adev)
1347{
1348 struct audio_usecase *usecase;
1349 struct listnode *node;
1350
1351 list_for_each_reverse(node, &adev->usecase_list) {
1352 usecase = node_to_item(node, struct audio_usecase, list);
1353 if (usecase->type == PCM_CAPTURE)
1354 return usecase->stream.in;
1355 }
1356 return NULL;
1357}
1358
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301359/*
1360 * is a true native playback active
1361 */
1362bool audio_is_true_native_stream_active(struct audio_device *adev)
1363{
1364 bool active = false;
1365 int i = 0;
1366 struct listnode *node;
1367
1368 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1369 ALOGV("%s:napb: not in true mode or non hdphones device",
1370 __func__);
1371 active = false;
1372 goto exit;
1373 }
1374
1375 list_for_each(node, &adev->usecase_list) {
1376 struct audio_usecase *uc;
1377 uc = node_to_item(node, struct audio_usecase, list);
1378 struct stream_out *curr_out =
1379 (struct stream_out*) uc->stream.out;
1380
1381 if (curr_out && PCM_PLAYBACK == uc->type) {
1382 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1383 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1384 uc->id, curr_out->sample_rate,
1385 curr_out->bit_width,
1386 platform_get_snd_device_name(uc->out_snd_device));
1387
1388 if (is_offload_usecase(uc->id) &&
1389 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1390 active = true;
1391 ALOGD("%s:napb:native stream detected", __func__);
1392 }
1393 }
1394 }
1395exit:
1396 return active;
1397}
1398
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301399/*
1400 * if native DSD playback active
1401 */
1402bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1403{
1404 bool active = false;
1405 struct listnode *node = NULL;
1406 struct audio_usecase *uc = NULL;
1407 struct stream_out *curr_out = NULL;
1408
1409 list_for_each(node, &adev->usecase_list) {
1410 uc = node_to_item(node, struct audio_usecase, list);
1411 curr_out = (struct stream_out*) uc->stream.out;
1412
1413 if (curr_out && PCM_PLAYBACK == uc->type &&
1414 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1415 active = true;
1416 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301417 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301418 }
1419 }
1420 return active;
1421}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301422
1423static bool force_device_switch(struct audio_usecase *usecase)
1424{
1425 bool ret = false;
1426 bool is_it_true_mode = false;
1427
1428 if (is_offload_usecase(usecase->id) &&
1429 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001430 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1431 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1432 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301433 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1434 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1435 (!is_it_true_mode && adev->native_playback_enabled)){
1436 ret = true;
1437 ALOGD("napb: time to toggle native mode");
1438 }
1439 }
1440
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301441 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301442 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1443 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301444 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001445 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301446 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301447 ALOGD("Force a2dp device switch to update new encoder config");
1448 ret = true;
1449 }
1450
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301451 return ret;
1452}
1453
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001454int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 snd_device_t out_snd_device = SND_DEVICE_NONE;
1457 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 struct audio_usecase *usecase = NULL;
1459 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001460 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001461 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001462 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301465 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 usecase = get_usecase_from_list(adev, uc_id);
1468 if (usecase == NULL) {
1469 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1470 return -EINVAL;
1471 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001472
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001473 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001474 (usecase->type == VOIP_CALL) ||
1475 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301476 if(usecase->stream.out == NULL) {
1477 ALOGE("%s: stream.out is NULL", __func__);
1478 return -EINVAL;
1479 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001480 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001481 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001482 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 usecase->devices = usecase->stream.out->devices;
1484 } else {
1485 /*
1486 * If the voice call is active, use the sound devices of voice call usecase
1487 * so that it would not result any device switch. All the usecases will
1488 * be switched to new device when select_devices() is called for voice call
1489 * usecase. This is to avoid switching devices for voice call when
1490 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001491 * choose voice call device only if the use case device is
1492 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001494 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001495 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001496 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001497 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1498 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301499 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1500 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001501 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 in_snd_device = vc_usecase->in_snd_device;
1503 out_snd_device = vc_usecase->out_snd_device;
1504 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001505 } else if (voice_extn_compress_voip_is_active(adev)) {
1506 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001507 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001508 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1509 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001510 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001511 in_snd_device = voip_usecase->in_snd_device;
1512 out_snd_device = voip_usecase->out_snd_device;
1513 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001514 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001515 hfp_ucid = audio_extn_hfp_get_usecase();
1516 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001517 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001518 in_snd_device = hfp_usecase->in_snd_device;
1519 out_snd_device = hfp_usecase->out_snd_device;
1520 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 }
1522 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301523 if (usecase->stream.out == NULL) {
1524 ALOGE("%s: stream.out is NULL", __func__);
1525 return -EINVAL;
1526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 usecase->devices = usecase->stream.out->devices;
1528 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001529 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001530 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001531 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001532 if (usecase->stream.out == adev->primary_output &&
1533 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001534 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001535 select_devices(adev, adev->active_input->usecase);
1536 }
1537 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301539 if (usecase->stream.in == NULL) {
1540 ALOGE("%s: stream.in is NULL", __func__);
1541 return -EINVAL;
1542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 usecase->devices = usecase->stream.in->device;
1544 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001545 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001546 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001547 if (adev->active_input &&
1548 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301549 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1550 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1551 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001552 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001553 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001554 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1555 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001556 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001557 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001558 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 }
1560 }
1561
1562 if (out_snd_device == usecase->out_snd_device &&
1563 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301564
1565 if (!force_device_switch(usecase))
1566 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567 }
1568
sangwoobc677242013-08-08 16:53:43 +09001569 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001570 out_snd_device, platform_get_snd_device_name(out_snd_device),
1571 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 /*
1574 * Limitation: While in call, to do a device switch we need to disable
1575 * and enable both RX and TX devices though one of them is same as current
1576 * device.
1577 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001578 if ((usecase->type == VOICE_CALL) &&
1579 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1580 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001581 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001582 }
1583
1584 if (((usecase->type == VOICE_CALL) ||
1585 (usecase->type == VOIP_CALL)) &&
1586 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1587 /* Disable sidetone only if voice/voip call already exists */
1588 if (voice_is_call_state_active(adev) ||
1589 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001590 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001591
1592 /* Disable aanc only if voice call exists */
1593 if (voice_is_call_state_active(adev))
1594 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001595 }
1596
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001597 /* Disable current sound devices */
1598 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001599 disable_audio_route(adev, usecase);
1600 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 }
1602
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001604 disable_audio_route(adev, usecase);
1605 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 }
1607
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001608 /* Applicable only on the targets that has external modem.
1609 * New device information should be sent to modem before enabling
1610 * the devices to reduce in-call device switch time.
1611 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001612 if ((usecase->type == VOICE_CALL) &&
1613 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1614 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001615 status = platform_switch_voice_call_enable_device_config(adev->platform,
1616 out_snd_device,
1617 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001618 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001619
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 /* Enable new sound devices */
1621 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001622 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001623 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 }
1625
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001626 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301627 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001628 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001629 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630
Avinash Vaish71a8b972014-07-24 15:36:33 +05301631 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001632 status = platform_switch_voice_call_device_post(adev->platform,
1633 out_snd_device,
1634 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301635 enable_audio_route_for_voice_usecases(adev, usecase);
1636 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001637
sangwoo170731f2013-06-08 15:36:36 +09001638 usecase->in_snd_device = in_snd_device;
1639 usecase->out_snd_device = out_snd_device;
1640
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301641 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1642 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301643 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001644 if ((24 == usecase->stream.out->bit_width) &&
1645 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1646 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1647 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1648 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1649 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1650 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1651 /*
1652 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1653 * configured device sample rate, if not update the COPP rate to be equal to the
1654 * device sample rate, else open COPP at stream sample rate
1655 */
1656 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1657 usecase->stream.out->sample_rate,
1658 &usecase->stream.out->app_type_cfg.sample_rate);
1659 } else if ((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1660 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1661 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1662 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1663 }
1664
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001665 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001666 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001667 audio_extn_gef_notify_device_config(
1668 usecase->stream.out->devices,
1669 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001670 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001671 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001672 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301673 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001674 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001675
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001676 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001677 /* Enable aanc only if voice call exists */
1678 if (voice_is_call_state_active(adev))
1679 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1680
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001681 /* Enable sidetone only if other voice/voip call already exists */
1682 if (voice_is_call_state_active(adev) ||
1683 voice_extn_compress_voip_is_started(adev))
1684 voice_set_sidetone(adev, out_snd_device, true);
1685 }
1686
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001687 /* Applicable only on the targets that has external modem.
1688 * Enable device command should be sent to modem only after
1689 * enabling voice call mixer controls
1690 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001691 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001692 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1693 out_snd_device,
1694 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301695 ALOGD("%s: done",__func__);
1696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697 return status;
1698}
1699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001700static int stop_input_stream(struct stream_in *in)
1701{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301702 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001703 struct audio_usecase *uc_info;
1704 struct audio_device *adev = in->dev;
1705
Eric Laurent994a6932013-07-17 11:51:42 -07001706 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 uc_info = get_usecase_from_list(adev, in->usecase);
1709 if (uc_info == NULL) {
1710 ALOGE("%s: Could not find the usecase (%d) in the list",
1711 __func__, in->usecase);
1712 return -EINVAL;
1713 }
1714
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001715 /* Close in-call recording streams */
1716 voice_check_and_stop_incall_rec_usecase(adev, in);
1717
Eric Laurent150dbfe2013-02-27 14:31:02 -08001718 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001719 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001720
1721 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001722 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001724 list_remove(&uc_info->list);
1725 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001727 adev->active_input = get_next_active_input(adev);
1728
Eric Laurent994a6932013-07-17 11:51:42 -07001729 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730 return ret;
1731}
1732
1733int start_input_stream(struct stream_in *in)
1734{
1735 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001736 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737 struct audio_usecase *uc_info;
1738 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301739 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740
Mingming Yin2664a5b2015-09-03 10:53:11 -07001741 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1742 if (get_usecase_from_list(adev, usecase) == NULL)
1743 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301744 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1745 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001746
Naresh Tanniru80659832014-06-04 18:17:56 +05301747
1748 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301749 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301750 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301751 goto error_config;
1752 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301753
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001754 /* Check if source matches incall recording usecase criteria */
1755 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1756 if (ret)
1757 goto error_config;
1758 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001759 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1760
1761 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1762 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1763 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001764 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001765 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001766
Eric Laurentb23d5282013-05-14 15:27:20 -07001767 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 if (in->pcm_device_id < 0) {
1769 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1770 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001771 ret = -EINVAL;
1772 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001774
1775 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001777
1778 if (!uc_info) {
1779 ret = -ENOMEM;
1780 goto error_config;
1781 }
1782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 uc_info->id = in->usecase;
1784 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001785 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001786 uc_info->devices = in->device;
1787 uc_info->in_snd_device = SND_DEVICE_NONE;
1788 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001790 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301791 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1792 adev->perf_lock_opts,
1793 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001794 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301796 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1797 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001798
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301799 if (audio_extn_cin_attached_usecase(in->usecase)) {
1800 ret = audio_extn_cin_start_input_stream(in);
1801 if (ret)
1802 goto error_open;
1803 else
1804 goto done_open;
1805 }
1806
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001807 unsigned int flags = PCM_IN;
1808 unsigned int pcm_open_retry_count = 0;
1809
1810 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1811 flags |= PCM_MMAP | PCM_NOIRQ;
1812 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001813 } else if (in->realtime) {
1814 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001815 }
1816
1817 while (1) {
1818 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1819 flags, &in->config);
1820 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1821 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1822 if (in->pcm != NULL) {
1823 pcm_close(in->pcm);
1824 in->pcm = NULL;
1825 }
1826 if (pcm_open_retry_count-- == 0) {
1827 ret = -EIO;
1828 goto error_open;
1829 }
1830 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1831 continue;
1832 }
1833 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001835
1836 ALOGV("%s: pcm_prepare", __func__);
1837 ret = pcm_prepare(in->pcm);
1838 if (ret < 0) {
1839 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1840 pcm_close(in->pcm);
1841 in->pcm = NULL;
1842 goto error_open;
1843 }
1844
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001845 register_in_stream(in);
1846 if (in->realtime) {
1847 ret = pcm_start(in->pcm);
1848 if (ret < 0)
1849 goto error_open;
1850 }
1851
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301852done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301853 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001854 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001855
Eric Laurentc8400632013-02-14 19:04:54 -08001856 return ret;
1857
1858error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301859 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001861error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301862 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301863 /*
1864 * sleep 50ms to allow sufficient time for kernel
1865 * drivers to recover incases like SSR.
1866 */
1867 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001868 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001869
1870 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871}
1872
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001873void lock_input_stream(struct stream_in *in)
1874{
1875 pthread_mutex_lock(&in->pre_lock);
1876 pthread_mutex_lock(&in->lock);
1877 pthread_mutex_unlock(&in->pre_lock);
1878}
1879
1880void lock_output_stream(struct stream_out *out)
1881{
1882 pthread_mutex_lock(&out->pre_lock);
1883 pthread_mutex_lock(&out->lock);
1884 pthread_mutex_unlock(&out->pre_lock);
1885}
1886
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001887/* must be called with out->lock locked */
1888static int send_offload_cmd_l(struct stream_out* out, int command)
1889{
1890 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1891
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001892 if (!cmd) {
1893 ALOGE("failed to allocate mem for command 0x%x", command);
1894 return -ENOMEM;
1895 }
1896
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001897 ALOGVV("%s %d", __func__, command);
1898
1899 cmd->cmd = command;
1900 list_add_tail(&out->offload_cmd_list, &cmd->node);
1901 pthread_cond_signal(&out->offload_cond);
1902 return 0;
1903}
1904
1905/* must be called iwth out->lock locked */
1906static void stop_compressed_output_l(struct stream_out *out)
1907{
1908 out->offload_state = OFFLOAD_STATE_IDLE;
1909 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001910 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001911 if (out->compr != NULL) {
1912 compress_stop(out->compr);
1913 while (out->offload_thread_blocked) {
1914 pthread_cond_wait(&out->cond, &out->lock);
1915 }
1916 }
1917}
1918
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001919bool is_offload_usecase(audio_usecase_t uc_id)
1920{
1921 unsigned int i;
1922 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1923 if (uc_id == offload_usecases[i])
1924 return true;
1925 }
1926 return false;
1927}
1928
vivek mehta446c3962015-09-14 10:57:35 -07001929static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001930{
vivek mehta446c3962015-09-14 10:57:35 -07001931 audio_usecase_t ret_uc = USECASE_INVALID;
1932 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001933 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001934 if (!adev->multi_offload_enable) {
1935 if (is_direct_pcm)
1936 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1937 else
1938 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001939
vivek mehta446c3962015-09-14 10:57:35 -07001940 pthread_mutex_lock(&adev->lock);
1941 if (get_usecase_from_list(adev, ret_uc) != NULL)
1942 ret_uc = USECASE_INVALID;
1943 pthread_mutex_unlock(&adev->lock);
1944
1945 return ret_uc;
1946 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001947
1948 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001949 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1950 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1951 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1952 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001953 break;
1954 }
1955 }
vivek mehta446c3962015-09-14 10:57:35 -07001956
1957 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1958 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001959}
1960
1961static void free_offload_usecase(struct audio_device *adev,
1962 audio_usecase_t uc_id)
1963{
vivek mehta446c3962015-09-14 10:57:35 -07001964 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001965 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001966
1967 if (!adev->multi_offload_enable)
1968 return;
1969
1970 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1971 if (offload_usecases[offload_uc_index] == uc_id) {
1972 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001973 break;
1974 }
1975 }
1976 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1977}
1978
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001979static void *offload_thread_loop(void *context)
1980{
1981 struct stream_out *out = (struct stream_out *) context;
1982 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001983 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001985 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1986 set_sched_policy(0, SP_FOREGROUND);
1987 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1988
1989 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001990 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991 for (;;) {
1992 struct offload_cmd *cmd = NULL;
1993 stream_callback_event_t event;
1994 bool send_callback = false;
1995
1996 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1997 __func__, list_empty(&out->offload_cmd_list),
1998 out->offload_state);
1999 if (list_empty(&out->offload_cmd_list)) {
2000 ALOGV("%s SLEEPING", __func__);
2001 pthread_cond_wait(&out->offload_cond, &out->lock);
2002 ALOGV("%s RUNNING", __func__);
2003 continue;
2004 }
2005
2006 item = list_head(&out->offload_cmd_list);
2007 cmd = node_to_item(item, struct offload_cmd, node);
2008 list_remove(item);
2009
2010 ALOGVV("%s STATE %d CMD %d out->compr %p",
2011 __func__, out->offload_state, cmd->cmd, out->compr);
2012
2013 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2014 free(cmd);
2015 break;
2016 }
2017
2018 if (out->compr == NULL) {
2019 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002020 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021 pthread_cond_signal(&out->cond);
2022 continue;
2023 }
2024 out->offload_thread_blocked = true;
2025 pthread_mutex_unlock(&out->lock);
2026 send_callback = false;
2027 switch(cmd->cmd) {
2028 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002029 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002031 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032 send_callback = true;
2033 event = STREAM_CBK_EVENT_WRITE_READY;
2034 break;
2035 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002036 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302037 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002038 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302039 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002040 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302041 if (ret < 0)
2042 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302043 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302044 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002045 compress_drain(out->compr);
2046 else
2047 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302048 if (ret != -ENETRESET) {
2049 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302050 pthread_mutex_lock(&out->lock);
2051 out->send_new_metadata = 1;
2052 out->send_next_track_params = true;
2053 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302054 event = STREAM_CBK_EVENT_DRAIN_READY;
2055 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2056 } else
2057 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 break;
2059 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002060 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002061 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002062 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 send_callback = true;
2064 event = STREAM_CBK_EVENT_DRAIN_READY;
2065 break;
2066 default:
2067 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2068 break;
2069 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002070 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002071 out->offload_thread_blocked = false;
2072 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002073 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002074 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002076 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077 free(cmd);
2078 }
2079
2080 pthread_cond_signal(&out->cond);
2081 while (!list_empty(&out->offload_cmd_list)) {
2082 item = list_head(&out->offload_cmd_list);
2083 list_remove(item);
2084 free(node_to_item(item, struct offload_cmd, node));
2085 }
2086 pthread_mutex_unlock(&out->lock);
2087
2088 return NULL;
2089}
2090
2091static int create_offload_callback_thread(struct stream_out *out)
2092{
2093 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2094 list_init(&out->offload_cmd_list);
2095 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2096 offload_thread_loop, out);
2097 return 0;
2098}
2099
2100static int destroy_offload_callback_thread(struct stream_out *out)
2101{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002102 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103 stop_compressed_output_l(out);
2104 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2105
2106 pthread_mutex_unlock(&out->lock);
2107 pthread_join(out->offload_thread, (void **) NULL);
2108 pthread_cond_destroy(&out->offload_cond);
2109
2110 return 0;
2111}
2112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113static int stop_output_stream(struct stream_out *out)
2114{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302115 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 struct audio_usecase *uc_info;
2117 struct audio_device *adev = out->dev;
2118
Eric Laurent994a6932013-07-17 11:51:42 -07002119 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002120 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 uc_info = get_usecase_from_list(adev, out->usecase);
2122 if (uc_info == NULL) {
2123 ALOGE("%s: Could not find the usecase (%d) in the list",
2124 __func__, out->usecase);
2125 return -EINVAL;
2126 }
2127
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002128 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302129 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002130 if (adev->visualizer_stop_output != NULL)
2131 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002132
2133 audio_extn_dts_remove_state_notifier_node(out->usecase);
2134
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002135 if (adev->offload_effects_stop_output != NULL)
2136 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2137 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002138
Eric Laurent150dbfe2013-02-27 14:31:02 -08002139 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002140 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002141
2142 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002143 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002145 list_remove(&uc_info->list);
2146 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002148 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302149 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002150 ALOGV("Disable passthrough , reset mixer to pcm");
2151 /* NO_PASSTHROUGH */
2152 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002153 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002154 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2155 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002156
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302157 /* Must be called after removing the usecase from list */
2158 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302159 audio_extn_keep_alive_start();
2160
Eric Laurent994a6932013-07-17 11:51:42 -07002161 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 return ret;
2163}
2164
2165int start_output_stream(struct stream_out *out)
2166{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 struct audio_usecase *uc_info;
2169 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302170 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002172 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2173 ret = -EINVAL;
2174 goto error_config;
2175 }
2176
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302177 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2178 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2179 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302180
Naresh Tanniru80659832014-06-04 18:17:56 +05302181 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302182 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302183 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302184 goto error_config;
2185 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302186
Eric Laurentb23d5282013-05-14 15:27:20 -07002187 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 if (out->pcm_device_id < 0) {
2189 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2190 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002191 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002192 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193 }
2194
2195 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002196
2197 if (!uc_info) {
2198 ret = -ENOMEM;
2199 goto error_config;
2200 }
2201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 uc_info->id = out->usecase;
2203 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002204 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002205 uc_info->devices = out->devices;
2206 uc_info->in_snd_device = SND_DEVICE_NONE;
2207 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002208 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302210 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2211 adev->perf_lock_opts,
2212 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302213
2214 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2215 audio_extn_keep_alive_stop();
2216 if (audio_extn_passthru_is_enabled() &&
2217 audio_extn_passthru_is_passthrough_stream(out)) {
2218 audio_extn_passthru_on_start(out);
2219 audio_extn_passthru_update_stream_configuration(adev, out);
2220 }
2221 }
2222
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223 select_devices(adev, out->usecase);
2224
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002225 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2226 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002227 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002228 unsigned int flags = PCM_OUT;
2229 unsigned int pcm_open_retry_count = 0;
2230 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2231 flags |= PCM_MMAP | PCM_NOIRQ;
2232 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002233 } else if (out->realtime) {
2234 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002235 } else
2236 flags |= PCM_MONOTONIC;
2237
2238 while (1) {
2239 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2240 flags, &out->config);
2241 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2242 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2243 if (out->pcm != NULL) {
2244 pcm_close(out->pcm);
2245 out->pcm = NULL;
2246 }
2247 if (pcm_open_retry_count-- == 0) {
2248 ret = -EIO;
2249 goto error_open;
2250 }
2251 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2252 continue;
2253 }
2254 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002255 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002256
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002257 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2258 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002259
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002260 ALOGV("%s: pcm_prepare", __func__);
2261 if (pcm_is_ready(out->pcm)) {
2262 ret = pcm_prepare(out->pcm);
2263 if (ret < 0) {
2264 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2265 pcm_close(out->pcm);
2266 out->pcm = NULL;
2267 goto error_open;
2268 }
2269 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002270 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002271 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2272 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002273 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002274 out->compr = compress_open(adev->snd_card,
2275 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002276 COMPRESS_IN, &out->compr_config);
2277 if (out->compr && !is_compress_ready(out->compr)) {
2278 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2279 compress_close(out->compr);
2280 out->compr = NULL;
2281 ret = -EIO;
2282 goto error_open;
2283 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302284 /* compress_open sends params of the track, so reset the flag here */
2285 out->is_compr_metadata_avail = false;
2286
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287 if (out->offload_callback)
2288 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002289
Fred Oh3f43e742015-03-04 18:42:34 -08002290 /* Since small bufs uses blocking writes, a write will be blocked
2291 for the default max poll time (20s) in the event of an SSR.
2292 Reduce the poll time to observe and deal with SSR faster.
2293 */
Ashish Jain5106d362016-05-11 19:23:33 +05302294 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002295 compress_set_max_poll_wait(out->compr, 1000);
2296 }
2297
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002298 audio_extn_dts_create_state_notifier_node(out->usecase);
2299 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2300 popcount(out->channel_mask),
2301 out->playback_started);
2302
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002303#ifdef DS1_DOLBY_DDP_ENABLED
2304 if (audio_extn_is_dolby_format(out->format))
2305 audio_extn_dolby_send_ddp_endp_params(adev);
2306#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302307 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2308 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002309 if (adev->visualizer_start_output != NULL)
2310 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2311 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302312 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002313 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002314 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002316
2317 if (ret == 0) {
2318 register_out_stream(out);
2319 if (out->realtime) {
2320 ret = pcm_start(out->pcm);
2321 if (ret < 0)
2322 goto error_open;
2323 }
2324 }
2325
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302326 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002327 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002328
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002329 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002330error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302331 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002333error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302334 /*
2335 * sleep 50ms to allow sufficient time for kernel
2336 * drivers to recover incases like SSR.
2337 */
2338 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002339 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340}
2341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342static int check_input_parameters(uint32_t sample_rate,
2343 audio_format_t format,
2344 int channel_count)
2345{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002346 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302348 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2349 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2350 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002351 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302352 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002353
2354 switch (channel_count) {
2355 case 1:
2356 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302357 case 3:
2358 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002359 case 6:
2360 break;
2361 default:
2362 ret = -EINVAL;
2363 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364
2365 switch (sample_rate) {
2366 case 8000:
2367 case 11025:
2368 case 12000:
2369 case 16000:
2370 case 22050:
2371 case 24000:
2372 case 32000:
2373 case 44100:
2374 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302375 case 96000:
2376 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377 break;
2378 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002379 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 }
2381
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002382 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383}
2384
2385static size_t get_input_buffer_size(uint32_t sample_rate,
2386 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002387 int channel_count,
2388 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389{
2390 size_t size = 0;
2391
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002392 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2393 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002395 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002396 if (is_low_latency)
2397 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302398
2399 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002401 /* make sure the size is multiple of 32 bytes
2402 * At 48 kHz mono 16-bit PCM:
2403 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2404 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2405 */
2406 size += 0x1f;
2407 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002408
2409 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410}
2411
Ashish Jain058165c2016-09-28 23:18:48 +05302412static size_t get_output_period_size(uint32_t sample_rate,
2413 audio_format_t format,
2414 int channel_count,
2415 int duration /*in millisecs*/)
2416{
2417 size_t size = 0;
2418 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2419
2420 if ((duration == 0) || (sample_rate == 0) ||
2421 (bytes_per_sample == 0) || (channel_count == 0)) {
2422 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2423 bytes_per_sample, channel_count);
2424 return -EINVAL;
2425 }
2426
2427 size = (sample_rate *
2428 duration *
2429 bytes_per_sample *
2430 channel_count) / 1000;
2431 /*
2432 * To have same PCM samples for all channels, the buffer size requires to
2433 * be multiple of (number of channels * bytes per sample)
2434 * For writes to succeed, the buffer must be written at address which is multiple of 32
2435 */
2436 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2437
2438 return (size/(channel_count * bytes_per_sample));
2439}
2440
Ashish Jain5106d362016-05-11 19:23:33 +05302441static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2442{
2443 uint64_t actual_frames_rendered = 0;
2444 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2445
2446 /* This adjustment accounts for buffering after app processor.
2447 * It is based on estimated DSP latency per use case, rather than exact.
2448 */
2449 int64_t platform_latency = platform_render_latency(out->usecase) *
2450 out->sample_rate / 1000000LL;
2451
2452 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2453 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2454 * hence only estimate.
2455 */
2456 int64_t signed_frames = out->written - kernel_buffer_size;
2457
2458 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2459
2460 if (signed_frames > 0)
2461 actual_frames_rendered = signed_frames;
2462
2463 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2464 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2465 (long long int)out->written, (int)kernel_buffer_size,
2466 audio_bytes_per_sample(out->compr_config.codec->format),
2467 popcount(out->channel_mask));
2468
2469 return actual_frames_rendered;
2470}
2471
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2473{
2474 struct stream_out *out = (struct stream_out *)stream;
2475
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002476 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477}
2478
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002479static int out_set_sample_rate(struct audio_stream *stream __unused,
2480 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481{
2482 return -ENOSYS;
2483}
2484
2485static size_t out_get_buffer_size(const struct audio_stream *stream)
2486{
2487 struct stream_out *out = (struct stream_out *)stream;
2488
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002489 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002490 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002491 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2492 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302493 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302494 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002495
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002496 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002497 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498}
2499
2500static uint32_t out_get_channels(const struct audio_stream *stream)
2501{
2502 struct stream_out *out = (struct stream_out *)stream;
2503
2504 return out->channel_mask;
2505}
2506
2507static audio_format_t out_get_format(const struct audio_stream *stream)
2508{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002509 struct stream_out *out = (struct stream_out *)stream;
2510
2511 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512}
2513
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002514static int out_set_format(struct audio_stream *stream __unused,
2515 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516{
2517 return -ENOSYS;
2518}
2519
2520static int out_standby(struct audio_stream *stream)
2521{
2522 struct stream_out *out = (struct stream_out *)stream;
2523 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002524
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302525 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2526 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002528 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002530 if (adev->adm_deregister_stream)
2531 adev->adm_deregister_stream(adev->adm_data, out->handle);
2532
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002533 if (is_offload_usecase(out->usecase))
2534 stop_compressed_output_l(out);
2535
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002536 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002538 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2539 voice_extn_compress_voip_close_output_stream(stream);
2540 pthread_mutex_unlock(&adev->lock);
2541 pthread_mutex_unlock(&out->lock);
2542 ALOGD("VOIP output entered standby");
2543 return 0;
2544 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002545 if (out->pcm) {
2546 pcm_close(out->pcm);
2547 out->pcm = NULL;
2548 }
2549 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002550 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302551 out->send_next_track_params = false;
2552 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002553 out->gapless_mdata.encoder_delay = 0;
2554 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002555 if (out->compr != NULL) {
2556 compress_close(out->compr);
2557 out->compr = NULL;
2558 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002559 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002561 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 }
2563 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302564 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 return 0;
2566}
2567
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002568static int out_dump(const struct audio_stream *stream __unused,
2569 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570{
2571 return 0;
2572}
2573
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002574static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2575{
2576 int ret = 0;
2577 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002578
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002579 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002580 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002581 return -EINVAL;
2582 }
2583
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302584 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002585
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002586 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2587 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302588 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002589 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002590 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2591 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302592 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002593 }
2594
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002595 ALOGV("%s new encoder delay %u and padding %u", __func__,
2596 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2597
2598 return 0;
2599}
2600
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002601static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2602{
2603 return out == adev->primary_output || out == adev->voice_tx_output;
2604}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2607{
2608 struct stream_out *out = (struct stream_out *)stream;
2609 struct audio_device *adev = out->dev;
2610 struct str_parms *parms;
2611 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002612 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613
sangwoobc677242013-08-08 16:53:43 +09002614 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002615 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302617 if (!parms)
2618 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002619 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2620 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002622 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002623 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002625 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002626 * When HDMI cable is unplugged the music playback is paused and
2627 * the policy manager sends routing=0. But the audioflinger continues
2628 * to write data until standby time (3sec). As the HDMI core is
2629 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002630 * Avoid this by routing audio to speaker until standby.
2631 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002632 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2633 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302634 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002635 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2636 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002637 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302638 /*
2639 * When A2DP is disconnected the
2640 * music playback is paused and the policy manager sends routing=0
2641 * But the audioflingercontinues to write data until standby time
2642 * (3sec). As BT is turned off, the write gets blocked.
2643 * Avoid this by routing audio to speaker until standby.
2644 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002645 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302646 (val == AUDIO_DEVICE_NONE)) {
2647 val = AUDIO_DEVICE_OUT_SPEAKER;
2648 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302649 /* To avoid a2dp to sco overlapping force route BT usecases
2650 * to speaker based on Phone state
2651 */
Ashish Jainc597d102016-12-12 10:31:34 +05302652 if ((((val & AUDIO_DEVICE_OUT_SPEAKER) &&
2653 (val & AUDIO_DEVICE_OUT_ALL_A2DP)) ||
2654 ((adev->snd_dev_ref_cnt[SND_DEVICE_OUT_BT_A2DP] == 0) &&
2655 (val & AUDIO_DEVICE_OUT_ALL_A2DP))) &&
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302656 ((adev->mode == AUDIO_MODE_RINGTONE) ||
2657 (adev->mode == AUDIO_MODE_IN_CALL))) {
2658 ALOGD("Forcing a2dp routing to speaker for ring/call mode");
2659 val = AUDIO_DEVICE_OUT_SPEAKER;
2660 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002661 /*
2662 * select_devices() call below switches all the usecases on the same
2663 * backend to the new device. Refer to check_usecases_codec_backend() in
2664 * the select_devices(). But how do we undo this?
2665 *
2666 * For example, music playback is active on headset (deep-buffer usecase)
2667 * and if we go to ringtones and select a ringtone, low-latency usecase
2668 * will be started on headset+speaker. As we can't enable headset+speaker
2669 * and headset devices at the same time, select_devices() switches the music
2670 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2671 * So when the ringtone playback is completed, how do we undo the same?
2672 *
2673 * We are relying on the out_set_parameters() call on deep-buffer output,
2674 * once the ringtone playback is ended.
2675 * NOTE: We should not check if the current devices are same as new devices.
2676 * Because select_devices() must be called to switch back the music
2677 * playback to headset.
2678 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002679 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002680 audio_devices_t new_dev = val;
2681 bool same_dev = out->devices == new_dev;
2682 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002684 if (output_drives_call(adev, out)) {
2685 if(!voice_is_in_call(adev)) {
2686 if (adev->mode == AUDIO_MODE_IN_CALL) {
2687 adev->current_call_output = out;
2688 ret = voice_start_call(adev);
2689 }
2690 } else {
2691 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002692 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002693 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002694 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002695
2696 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002697 if (!same_dev) {
2698 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302699 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2700 adev->perf_lock_opts,
2701 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002702 if (adev->adm_on_routing_change)
2703 adev->adm_on_routing_change(adev->adm_data,
2704 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002705 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002706 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302707 if (!same_dev)
2708 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002709 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002710 }
2711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002713 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002715
2716 if (out == adev->primary_output) {
2717 pthread_mutex_lock(&adev->lock);
2718 audio_extn_set_parameters(adev, parms);
2719 pthread_mutex_unlock(&adev->lock);
2720 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002721 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002722 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002723 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002724
2725 audio_extn_dts_create_state_notifier_node(out->usecase);
2726 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2727 popcount(out->channel_mask),
2728 out->playback_started);
2729
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002730 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002731 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002732
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302733 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2734 if (err >= 0) {
2735 strlcpy(out->profile, value, sizeof(out->profile));
2736 ALOGV("updating stream profile with value '%s'", out->profile);
2737 lock_output_stream(out);
2738 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2739 &adev->streams_output_cfg_list,
2740 out->devices, out->flags, out->format,
2741 out->sample_rate, out->bit_width,
2742 out->channel_mask, out->profile,
2743 &out->app_type_cfg);
2744 pthread_mutex_unlock(&out->lock);
2745 }
2746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302748error:
Eric Laurent994a6932013-07-17 11:51:42 -07002749 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 return ret;
2751}
2752
2753static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2754{
2755 struct stream_out *out = (struct stream_out *)stream;
2756 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002757 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 char value[256];
2759 struct str_parms *reply = str_parms_create();
2760 size_t i, j;
2761 int ret;
2762 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002763
2764 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002765 if (reply) {
2766 str_parms_destroy(reply);
2767 }
2768 if (query) {
2769 str_parms_destroy(query);
2770 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002771 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2772 return NULL;
2773 }
2774
Eric Laurent994a6932013-07-17 11:51:42 -07002775 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2777 if (ret >= 0) {
2778 value[0] = '\0';
2779 i = 0;
2780 while (out->supported_channel_masks[i] != 0) {
2781 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2782 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2783 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002784 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002786 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787 first = false;
2788 break;
2789 }
2790 }
2791 i++;
2792 }
2793 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2794 str = str_parms_to_str(reply);
2795 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002796 voice_extn_out_get_parameters(out, query, reply);
2797 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002798 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002799 free(str);
2800 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002803
Alexy Joseph62142aa2015-11-16 15:10:34 -08002804
2805 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2806 if (ret >= 0) {
2807 value[0] = '\0';
2808 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2809 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302810 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002811 } else {
2812 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302813 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002814 }
2815 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002816 if (str)
2817 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002818 str = str_parms_to_str(reply);
2819 }
2820
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002821 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2822 if (ret >= 0) {
2823 value[0] = '\0';
2824 i = 0;
2825 first = true;
2826 while (out->supported_formats[i] != 0) {
2827 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2828 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2829 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002830 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002831 }
2832 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2833 first = false;
2834 break;
2835 }
2836 }
2837 i++;
2838 }
2839 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002840 if (str)
2841 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002842 str = str_parms_to_str(reply);
2843 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002844
2845 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2846 if (ret >= 0) {
2847 value[0] = '\0';
2848 i = 0;
2849 first = true;
2850 while (out->supported_sample_rates[i] != 0) {
2851 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2852 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2853 if (!first) {
2854 strlcat(value, "|", sizeof(value));
2855 }
2856 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2857 first = false;
2858 break;
2859 }
2860 }
2861 i++;
2862 }
2863 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2864 if (str)
2865 free(str);
2866 str = str_parms_to_str(reply);
2867 }
2868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002869 str_parms_destroy(query);
2870 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002871 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872 return str;
2873}
2874
2875static uint32_t out_get_latency(const struct audio_stream_out *stream)
2876{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002877 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002879 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880
Alexy Josephaa54c872014-12-03 02:46:47 -08002881 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002882 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002883 } else if (out->realtime) {
2884 // since the buffer won't be filled up faster than realtime,
2885 // return a smaller number
2886 if (out->config.rate)
2887 period_ms = (out->af_period_multiplier * out->config.period_size *
2888 1000) / (out->config.rate);
2889 else
2890 period_ms = 0;
2891 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002892 } else {
2893 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002895 }
2896
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302897 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002898 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899}
2900
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302901static float AmpToDb(float amplification)
2902{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302903 float db = DSD_VOLUME_MIN_DB;
2904 if (amplification > 0) {
2905 db = 20 * log10(amplification);
2906 if(db < DSD_VOLUME_MIN_DB)
2907 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302908 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302909 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302910}
2911
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912static int out_set_volume(struct audio_stream_out *stream, float left,
2913 float right)
2914{
Eric Laurenta9024de2013-04-04 09:19:12 -07002915 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002916 int volume[2];
2917
Eric Laurenta9024de2013-04-04 09:19:12 -07002918 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2919 /* only take left channel into account: the API is for stereo anyway */
2920 out->muted = (left == 0.0f);
2921 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002922 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302923 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002924 /*
2925 * Set mute or umute on HDMI passthrough stream.
2926 * Only take left channel into account.
2927 * Mute is 0 and unmute 1
2928 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302929 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302930 } else if (out->format == AUDIO_FORMAT_DSD){
2931 char mixer_ctl_name[128] = "DSD Volume";
2932 struct audio_device *adev = out->dev;
2933 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2934
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)(AmpToDb(left));
2941 volume[1] = (int)(AmpToDb(right));
2942 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2943 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002944 } else {
2945 char mixer_ctl_name[128];
2946 struct audio_device *adev = out->dev;
2947 struct mixer_ctl *ctl;
2948 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002949 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002951 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2952 "Compress Playback %d Volume", pcm_device_id);
2953 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2954 if (!ctl) {
2955 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2956 __func__, mixer_ctl_name);
2957 return -EINVAL;
2958 }
2959 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2960 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2961 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2962 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002963 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002964 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 return -ENOSYS;
2967}
2968
2969static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2970 size_t bytes)
2971{
2972 struct stream_out *out = (struct stream_out *)stream;
2973 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302974 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002975 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002977 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302978
Naresh Tanniru80659832014-06-04 18:17:56 +05302979 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002980
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302981 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302982 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302983 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2984 pthread_mutex_unlock(&out->lock);
2985 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302986 } else {
2987 /* increase written size during SSR to avoid mismatch
2988 * with the written frames count in AF
2989 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07002990 // bytes per frame
2991 size_t bpf = audio_bytes_per_sample(out->format) *
2992 audio_channel_count_from_out_mask(out->channel_mask);
2993 if (bpf != 0)
2994 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05302995 ALOGD(" %s: sound card is not active/SSR state", __func__);
2996 ret= -EIO;
2997 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302998 }
2999 }
3000
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303001 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303002 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3003 if (audio_bytes_per_sample(out->format) != 0)
3004 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3005 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303006 goto exit;
3007 }
3008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003010 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003011 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003012 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3013 ret = voice_extn_compress_voip_start_output_stream(out);
3014 else
3015 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003016 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003017 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003019 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 goto exit;
3021 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003022
3023 if (last_known_cal_step != -1) {
3024 ALOGD("%s: retry previous failed cal level set", __func__);
3025 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3026 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028
Ashish Jain81eb2a82015-05-13 10:52:34 +05303029 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003030 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303031 adev->is_channel_status_set = true;
3032 }
3033
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003034 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003035 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003036 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003037 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003038 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3039 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303040 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3041 ALOGD("copl(%p):send next track params in gapless", out);
3042 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3043 out->send_next_track_params = false;
3044 out->is_compr_metadata_avail = false;
3045 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003046 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303047 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303048 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003049
Ashish Jain83a6cc22016-06-28 14:34:17 +05303050 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303051 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303052 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303053 pthread_mutex_unlock(&out->lock);
3054 return -EINVAL;
3055 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303056 audio_format_t dst_format = out->hal_op_format;
3057 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303058
3059 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3060 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3061
Ashish Jain83a6cc22016-06-28 14:34:17 +05303062 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303063 dst_format,
3064 buffer,
3065 src_format,
3066 frames);
3067
Ashish Jain83a6cc22016-06-28 14:34:17 +05303068 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303069 bytes_to_write);
3070
3071 /*Convert written bytes in audio flinger format*/
3072 if (ret > 0)
3073 ret = ((ret * format_to_bitwidth_table[out->format]) /
3074 format_to_bitwidth_table[dst_format]);
3075 }
3076 } else
3077 ret = compress_write(out->compr, buffer, bytes);
3078
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303079 if (ret < 0)
3080 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303081 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303082 /*msg to cb thread only if non blocking write is enabled*/
3083 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303084 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303086 } else if (-ENETRESET == ret) {
3087 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3088 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3089 pthread_mutex_unlock(&out->lock);
3090 out_standby(&out->stream.common);
3091 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003092 }
Ashish Jain5106d362016-05-11 19:23:33 +05303093 if ( ret == (ssize_t)bytes && !out->non_blocking)
3094 out->written += bytes;
3095
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303096 /* Call compr start only when non-zero bytes of data is there to be rendered */
3097 if (!out->playback_started && ret > 0) {
3098 int status = compress_start(out->compr);
3099 if (status < 0) {
3100 ret = status;
3101 ALOGE("%s: compr start failed with err %d", __func__, errno);
3102 goto exit;
3103 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003104 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 out->playback_started = 1;
3106 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003107
3108 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3109 popcount(out->channel_mask),
3110 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003111 }
3112 pthread_mutex_unlock(&out->lock);
3113 return ret;
3114 } else {
3115 if (out->pcm) {
3116 if (out->muted)
3117 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003118
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303119 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003120
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003121 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003122
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003123 if (out->config.rate)
3124 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3125 out->config.rate;
3126
3127 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3128
3129 request_out_focus(out, ns);
3130
3131 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003132 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003133 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303134 out->convert_buffer != NULL) {
3135
3136 memcpy_by_audio_format(out->convert_buffer,
3137 out->hal_op_format,
3138 buffer,
3139 out->hal_ip_format,
3140 out->config.period_size * out->config.channels);
3141
3142 ret = pcm_write(out->pcm, out->convert_buffer,
3143 (out->config.period_size *
3144 out->config.channels *
3145 format_to_bitwidth_table[out->hal_op_format]));
3146 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003147 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303148 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003149
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003150 release_out_focus(out);
3151
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303152 if (ret < 0)
3153 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303154 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3155 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3156 else
3157 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 }
3160
3161exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303162 /* ToDo: There may be a corner case when SSR happens back to back during
3163 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303164 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303165 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303166 }
3167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 pthread_mutex_unlock(&out->lock);
3169
3170 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003171 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003172 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303173 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303174 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303175 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303176 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303177 out->standby = true;
3178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303180 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3181 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3182 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183 }
3184 return bytes;
3185}
3186
3187static int out_get_render_position(const struct audio_stream_out *stream,
3188 uint32_t *dsp_frames)
3189{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303191 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003192
3193 if (dsp_frames == NULL)
3194 return -EINVAL;
3195
3196 *dsp_frames = 0;
3197 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003198 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303199
3200 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3201 * this operation and adev_close_output_stream(where out gets reset).
3202 */
3203 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3204 *dsp_frames = get_actual_pcm_frames_rendered(out);
3205 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3206 return 0;
3207 }
3208
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003209 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303210 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303211 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003212 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303213 if (ret < 0)
3214 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303216 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 }
3218 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303219 if (-ENETRESET == ret) {
3220 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3221 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3222 return -EINVAL;
3223 } else if(ret < 0) {
3224 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3225 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303226 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3227 /*
3228 * Handle corner case where compress session is closed during SSR
3229 * and timestamp is queried
3230 */
3231 ALOGE(" ERROR: sound card not active, return error");
3232 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303233 } else {
3234 return 0;
3235 }
Zhou Song32a556e2015-05-05 10:46:56 +08003236 } else if (audio_is_linear_pcm(out->format)) {
3237 *dsp_frames = out->written;
3238 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003239 } else
3240 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241}
3242
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003243static int out_add_audio_effect(const struct audio_stream *stream __unused,
3244 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245{
3246 return 0;
3247}
3248
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003249static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3250 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251{
3252 return 0;
3253}
3254
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003255static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3256 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257{
3258 return -EINVAL;
3259}
3260
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003261static int out_get_presentation_position(const struct audio_stream_out *stream,
3262 uint64_t *frames, struct timespec *timestamp)
3263{
3264 struct stream_out *out = (struct stream_out *)stream;
3265 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003266 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003267
Ashish Jain5106d362016-05-11 19:23:33 +05303268 /* below piece of code is not guarded against any lock because audioFliner serializes
3269 * this operation and adev_close_output_stream( where out gets reset).
3270 */
3271 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3272 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3273 *frames = get_actual_pcm_frames_rendered(out);
3274 /* this is the best we can do */
3275 clock_gettime(CLOCK_MONOTONIC, timestamp);
3276 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3277 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3278 return 0;
3279 }
3280
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003281 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003282
Ashish Jain5106d362016-05-11 19:23:33 +05303283 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3284 ret = compress_get_tstamp(out->compr, &dsp_frames,
3285 &out->sample_rate);
3286 ALOGVV("%s rendered frames %ld sample_rate %d",
3287 __func__, dsp_frames, out->sample_rate);
3288 *frames = dsp_frames;
3289 if (ret < 0)
3290 ret = -errno;
3291 if (-ENETRESET == ret) {
3292 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3293 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3294 ret = -EINVAL;
3295 } else
3296 ret = 0;
3297 /* this is the best we can do */
3298 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003299 } else {
3300 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003301 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003302 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3303 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003304 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003305 // This adjustment accounts for buffering after app processor.
3306 // It is based on estimated DSP latency per use case, rather than exact.
3307 signed_frames -=
3308 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3309
Eric Laurent949a0892013-09-20 09:20:13 -07003310 // It would be unusual for this value to be negative, but check just in case ...
3311 if (signed_frames >= 0) {
3312 *frames = signed_frames;
3313 ret = 0;
3314 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003315 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303316 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3317 *frames = out->written;
3318 clock_gettime(CLOCK_MONOTONIC, timestamp);
3319 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003320 }
3321 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003322 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003323 return ret;
3324}
3325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326static int out_set_callback(struct audio_stream_out *stream,
3327 stream_callback_t callback, void *cookie)
3328{
3329 struct stream_out *out = (struct stream_out *)stream;
3330
3331 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003332 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003333 out->offload_callback = callback;
3334 out->offload_cookie = cookie;
3335 pthread_mutex_unlock(&out->lock);
3336 return 0;
3337}
3338
3339static int out_pause(struct audio_stream_out* stream)
3340{
3341 struct stream_out *out = (struct stream_out *)stream;
3342 int status = -ENOSYS;
3343 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003344 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003345 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003346 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003347 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303348 struct audio_device *adev = out->dev;
3349 int snd_scard_state = get_snd_card_state(adev);
3350
3351 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3352 status = compress_pause(out->compr);
3353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003354 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003355
Mingming Yin21854652016-04-13 11:54:02 -07003356 if (audio_extn_passthru_is_active()) {
3357 ALOGV("offload use case, pause passthru");
3358 audio_extn_passthru_on_pause(out);
3359 }
3360
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303361 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003362 audio_extn_dts_notify_playback_state(out->usecase, 0,
3363 out->sample_rate, popcount(out->channel_mask),
3364 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 }
3366 pthread_mutex_unlock(&out->lock);
3367 }
3368 return status;
3369}
3370
3371static int out_resume(struct audio_stream_out* stream)
3372{
3373 struct stream_out *out = (struct stream_out *)stream;
3374 int status = -ENOSYS;
3375 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003376 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003377 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003378 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003380 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303381 struct audio_device *adev = out->dev;
3382 int snd_scard_state = get_snd_card_state(adev);
3383
Mingming Yin21854652016-04-13 11:54:02 -07003384 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3385 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3386 pthread_mutex_lock(&out->dev->lock);
3387 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003388 pthread_mutex_unlock(&out->dev->lock);
3389 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303390 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003391 }
3392 if (!status) {
3393 out->offload_state = OFFLOAD_STATE_PLAYING;
3394 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303395 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003396 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3397 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003398 }
3399 pthread_mutex_unlock(&out->lock);
3400 }
3401 return status;
3402}
3403
3404static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3405{
3406 struct stream_out *out = (struct stream_out *)stream;
3407 int status = -ENOSYS;
3408 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003409 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003410 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003411 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3412 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3413 else
3414 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3415 pthread_mutex_unlock(&out->lock);
3416 }
3417 return status;
3418}
3419
3420static int out_flush(struct audio_stream_out* stream)
3421{
3422 struct stream_out *out = (struct stream_out *)stream;
3423 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003424 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003425 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003426 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003427 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3428 stop_compressed_output_l(out);
3429 out->written = 0;
3430 } else {
3431 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3432 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003434 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 return 0;
3436 }
3437 return -ENOSYS;
3438}
3439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440/** audio_stream_in implementation **/
3441static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3442{
3443 struct stream_in *in = (struct stream_in *)stream;
3444
3445 return in->config.rate;
3446}
3447
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003448static int in_set_sample_rate(struct audio_stream *stream __unused,
3449 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450{
3451 return -ENOSYS;
3452}
3453
3454static size_t in_get_buffer_size(const struct audio_stream *stream)
3455{
3456 struct stream_in *in = (struct stream_in *)stream;
3457
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003458 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3459 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003460 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3461 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303462 else if(audio_extn_cin_attached_usecase(in->usecase))
3463 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003464
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003465 return in->config.period_size * in->af_period_multiplier *
3466 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467}
3468
3469static uint32_t in_get_channels(const struct audio_stream *stream)
3470{
3471 struct stream_in *in = (struct stream_in *)stream;
3472
3473 return in->channel_mask;
3474}
3475
3476static audio_format_t in_get_format(const struct audio_stream *stream)
3477{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003478 struct stream_in *in = (struct stream_in *)stream;
3479
3480 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481}
3482
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003483static int in_set_format(struct audio_stream *stream __unused,
3484 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485{
3486 return -ENOSYS;
3487}
3488
3489static int in_standby(struct audio_stream *stream)
3490{
3491 struct stream_in *in = (struct stream_in *)stream;
3492 struct audio_device *adev = in->dev;
3493 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303494 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3495 stream, in->usecase, use_case_table[in->usecase]);
3496
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003497 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003498 if (!in->standby && in->is_st_session) {
3499 ALOGD("%s: sound trigger pcm stop lab", __func__);
3500 audio_extn_sound_trigger_stop_lab(in);
3501 in->standby = 1;
3502 }
3503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003505 if (adev->adm_deregister_stream)
3506 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3507
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003508 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003510 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3511 voice_extn_compress_voip_close_input_stream(stream);
3512 ALOGD("VOIP input entered standby");
3513 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303514 if (audio_extn_cin_attached_usecase(in->usecase))
3515 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003516 if (in->pcm) {
3517 pcm_close(in->pcm);
3518 in->pcm = NULL;
3519 }
3520 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003521 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003522 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523 }
3524 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003525 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526 return status;
3527}
3528
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003529static int in_dump(const struct audio_stream *stream __unused,
3530 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531{
3532 return 0;
3533}
3534
3535static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3536{
3537 struct stream_in *in = (struct stream_in *)stream;
3538 struct audio_device *adev = in->dev;
3539 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003541 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303543 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544 parms = str_parms_create_str(kvpairs);
3545
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303546 if (!parms)
3547 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003548 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003549 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003550
3551 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3552 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 val = atoi(value);
3554 /* no audio source uses val == 0 */
3555 if ((in->source != val) && (val != 0)) {
3556 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003557 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3558 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3559 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003560 (in->config.rate == 8000 || in->config.rate == 16000 ||
3561 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003562 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003563 err = voice_extn_compress_voip_open_input_stream(in);
3564 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003565 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003566 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003567 }
3568 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 }
3570 }
3571
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003572 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3573 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003575 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 in->device = val;
3577 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003578 if (!in->standby && !in->is_st_session) {
3579 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003580 if (adev->adm_on_routing_change)
3581 adev->adm_on_routing_change(adev->adm_data,
3582 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003583 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003584 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 }
3586 }
3587
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303588 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3589 if (err >= 0) {
3590 strlcpy(in->profile, value, sizeof(in->profile));
3591 ALOGV("updating stream profile with value '%s'", in->profile);
3592 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3593 &adev->streams_input_cfg_list,
3594 in->device, in->flags, in->format,
3595 in->sample_rate, in->bit_width,
3596 in->profile, &in->app_type_cfg);
3597 }
3598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003600 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601
3602 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303603error:
Eric Laurent994a6932013-07-17 11:51:42 -07003604 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 return ret;
3606}
3607
3608static char* in_get_parameters(const struct audio_stream *stream,
3609 const char *keys)
3610{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003611 struct stream_in *in = (struct stream_in *)stream;
3612 struct str_parms *query = str_parms_create_str(keys);
3613 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003614 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003615
3616 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003617 if (reply) {
3618 str_parms_destroy(reply);
3619 }
3620 if (query) {
3621 str_parms_destroy(query);
3622 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003623 ALOGE("in_get_parameters: failed to create query or reply");
3624 return NULL;
3625 }
3626
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003627 ALOGV("%s: enter: keys - %s", __func__, keys);
3628
3629 voice_extn_in_get_parameters(in, query, reply);
3630
3631 str = str_parms_to_str(reply);
3632 str_parms_destroy(query);
3633 str_parms_destroy(reply);
3634
3635 ALOGV("%s: exit: returns - %s", __func__, str);
3636 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637}
3638
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003639static int in_set_gain(struct audio_stream_in *stream __unused,
3640 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641{
3642 return 0;
3643}
3644
3645static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3646 size_t bytes)
3647{
3648 struct stream_in *in = (struct stream_in *)stream;
3649 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303650 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303651 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303652 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003654 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303655
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003656 if (in->is_st_session) {
3657 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3658 /* Read from sound trigger HAL */
3659 audio_extn_sound_trigger_read(in, buffer, bytes);
3660 pthread_mutex_unlock(&in->lock);
3661 return bytes;
3662 }
3663
Ashish Jainbbce4322016-02-16 13:25:27 +05303664 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003665 ALOGD(" %s: sound card is not active/SSR state", __func__);
3666 ret= -EIO;;
3667 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303668 }
3669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003671 pthread_mutex_lock(&adev->lock);
3672 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3673 ret = voice_extn_compress_voip_start_input_stream(in);
3674 else
3675 ret = start_input_stream(in);
3676 pthread_mutex_unlock(&adev->lock);
3677 if (ret != 0) {
3678 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003679 }
3680 in->standby = 0;
3681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003683 // what's the duration requested by the client?
3684 long ns = 0;
3685
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303686 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003687 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3688 in->config.rate;
3689
3690 request_in_focus(in, ns);
3691 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003692
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303693 if (audio_extn_cin_attached_usecase(in->usecase)) {
3694 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3695 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303696 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003697 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303698 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003699 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003700 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003701 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303702 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003703 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303704 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3705 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3706 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3707 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303708 ret = -EINVAL;
3709 goto exit;
3710 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303711 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303712 ret = -errno;
3713 }
3714 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303715 /* bytes read is always set to bytes for non compress usecases */
3716 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 }
3718
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003719 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 /*
3722 * Instead of writing zeroes here, we could trust the hardware
3723 * to always provide zeroes when muted.
3724 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303725 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3726 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 memset(buffer, 0, bytes);
3728
3729exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303730 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303731 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003732 if (-ENETRESET == ret)
3733 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 pthread_mutex_unlock(&in->lock);
3736
3737 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303738 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303739 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303740 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303741 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303742 in->standby = true;
3743 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303744 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003746 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303747 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303748 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303750 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751}
3752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003753static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754{
3755 return 0;
3756}
3757
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003758static int add_remove_audio_effect(const struct audio_stream *stream,
3759 effect_handle_t effect,
3760 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003762 struct stream_in *in = (struct stream_in *)stream;
3763 int status = 0;
3764 effect_descriptor_t desc;
3765
3766 status = (*effect)->get_descriptor(effect, &desc);
3767 if (status != 0)
3768 return status;
3769
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003770 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003771 pthread_mutex_lock(&in->dev->lock);
3772 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3773 in->enable_aec != enable &&
3774 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3775 in->enable_aec = enable;
3776 if (!in->standby)
3777 select_devices(in->dev, in->usecase);
3778 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003779 if (in->enable_ns != enable &&
3780 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3781 in->enable_ns = enable;
3782 if (!in->standby)
3783 select_devices(in->dev, in->usecase);
3784 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003785 pthread_mutex_unlock(&in->dev->lock);
3786 pthread_mutex_unlock(&in->lock);
3787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 return 0;
3789}
3790
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003791static int in_add_audio_effect(const struct audio_stream *stream,
3792 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793{
Eric Laurent994a6932013-07-17 11:51:42 -07003794 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003795 return add_remove_audio_effect(stream, effect, true);
3796}
3797
3798static int in_remove_audio_effect(const struct audio_stream *stream,
3799 effect_handle_t effect)
3800{
Eric Laurent994a6932013-07-17 11:51:42 -07003801 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003802 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803}
3804
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303805int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 audio_io_handle_t handle,
3807 audio_devices_t devices,
3808 audio_output_flags_t flags,
3809 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003810 struct audio_stream_out **stream_out,
3811 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812{
3813 struct audio_device *adev = (struct audio_device *)dev;
3814 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303815 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003816 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303819
3820 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3821 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003822 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303823 return -EINVAL;
3824 }
3825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3827
Mingming Yin3a941d42016-02-17 18:08:05 -08003828 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3829 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303830 devices, flags, &out->stream);
3831
3832
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003833 if (!out) {
3834 return -ENOMEM;
3835 }
3836
Haynes Mathew George204045b2015-02-25 20:32:03 -08003837 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003838 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003839 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 if (devices == AUDIO_DEVICE_NONE)
3842 devices = AUDIO_DEVICE_OUT_SPEAKER;
3843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 out->flags = flags;
3845 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003846 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003847 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003848 out->sample_rate = config->sample_rate;
3849 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3850 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003851 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003852 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003853 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303854 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855
Mingming Yin3a941d42016-02-17 18:08:05 -08003856 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3857 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3858 pthread_mutex_lock(&adev->lock);
3859 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3860 ret = read_hdmi_sink_caps(out);
3861 pthread_mutex_unlock(&adev->lock);
3862 if (ret != 0) {
3863 if (ret == -ENOSYS) {
3864 /* ignore and go with default */
3865 ret = 0;
3866 } else {
3867 ALOGE("error reading hdmi sink caps");
3868 goto error_open;
3869 }
3870 }
3871 }
3872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003874 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303875 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3876 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003877 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3878 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3879
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003880 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003881 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3882 /*
3883 * Do not handle stereo output in Multi-channel cases
3884 * Stereo case is handled in normal playback path
3885 */
3886 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3887 ret = AUDIO_CHANNEL_OUT_STEREO;
3888 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003889
3890 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3891 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003892 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003893 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003894 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003895
3896 if (config->sample_rate == 0)
3897 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3898 if (config->channel_mask == 0)
3899 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003900 if (config->format == 0)
3901 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003902
3903 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003904 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003905 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3907 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003909 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003911 } 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 -08003912 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003913 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003914 ret = voice_extn_compress_voip_open_output_stream(out);
3915 if (ret != 0) {
3916 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3917 __func__, ret);
3918 goto error_open;
3919 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003920 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3921 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3922
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003923 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3924 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3925 ALOGE("%s: Unsupported Offload information", __func__);
3926 ret = -EINVAL;
3927 goto error_open;
3928 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003929
Mingming Yin3a941d42016-02-17 18:08:05 -08003930 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003931 if(config->offload_info.format == 0)
3932 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003933 if (config->offload_info.sample_rate == 0)
3934 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003935 }
3936
Mingming Yin90310102013-11-13 16:57:00 -08003937 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303938 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003939 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003940 ret = -EINVAL;
3941 goto error_open;
3942 }
3943
3944 out->compr_config.codec = (struct snd_codec *)
3945 calloc(1, sizeof(struct snd_codec));
3946
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003947 if (!out->compr_config.codec) {
3948 ret = -ENOMEM;
3949 goto error_open;
3950 }
3951
vivek mehta0ea887a2015-08-26 14:01:20 -07003952 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303953 out->stream.pause = out_pause;
3954 out->stream.flush = out_flush;
3955 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003956 out->usecase = get_offload_usecase(adev, true);
3957 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003958 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003959 out->stream.set_callback = out_set_callback;
3960 out->stream.pause = out_pause;
3961 out->stream.resume = out_resume;
3962 out->stream.drain = out_drain;
3963 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003964 out->usecase = get_offload_usecase(adev, false);
3965 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003966 }
vivek mehta446c3962015-09-14 10:57:35 -07003967
3968 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003969 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3970 config->format == 0 && config->sample_rate == 0 &&
3971 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003972 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003973 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3974 } else {
3975 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3976 ret = -EEXIST;
3977 goto error_open;
3978 }
vivek mehta446c3962015-09-14 10:57:35 -07003979 }
3980
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003981 if (config->offload_info.channel_mask)
3982 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003983 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003985 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003986 } else {
3987 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
3988 ret = -EINVAL;
3989 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003990 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003991
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003992 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003993 out->sample_rate = config->offload_info.sample_rate;
3994
Mingming Yin3ee55c62014-08-04 14:23:35 -07003995 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003996
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303997 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3998 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3999 audio_extn_dolby_send_ddp_endp_params(adev);
4000 audio_extn_dolby_set_dmid(adev);
4001 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004002
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004003 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004004 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004005 out->compr_config.codec->bit_rate =
4006 config->offload_info.bit_rate;
4007 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304008 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004009 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304010 /* Update bit width only for non passthrough usecases.
4011 * For passthrough usecases, the output will always be opened @16 bit
4012 */
4013 if (!audio_extn_passthru_is_passthrough_stream(out))
4014 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004015 /*TODO: Do we need to change it for passthrough */
4016 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004017
Manish Dewangana6fc5442015-08-24 20:30:31 +05304018 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4019 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304020 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304021 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304022 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4023 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304024
4025 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4026 AUDIO_FORMAT_PCM) {
4027
4028 /*Based on platform support, configure appropriate alsa format for corresponding
4029 *hal input format.
4030 */
4031 out->compr_config.codec->format = hal_format_to_alsa(
4032 config->offload_info.format);
4033
Ashish Jain83a6cc22016-06-28 14:34:17 +05304034 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304035 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304036 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304037
4038 /*for direct PCM playback populate bit_width based on selected alsa format as
4039 *hal input format and alsa format might differ based on platform support.
4040 */
4041 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304042 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304043
4044 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4045
4046 /* Check if alsa session is configured with the same format as HAL input format,
4047 * if not then derive correct fragment size needed to accomodate the
4048 * conversion of HAL input format to alsa format.
4049 */
4050 audio_extn_utils_update_direct_pcm_fragment_size(out);
4051
4052 /*if hal input and output fragment size is different this indicates HAL input format is
4053 *not same as the alsa format
4054 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304055 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304056 /*Allocate a buffer to convert input data to the alsa configured format.
4057 *size of convert buffer is equal to the size required to hold one fragment size
4058 *worth of pcm data, this is because flinger does not write more than fragment_size
4059 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304060 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4061 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304062 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4063 ret = -ENOMEM;
4064 goto error_open;
4065 }
4066 }
4067 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4068 out->compr_config.fragment_size =
4069 audio_extn_passthru_get_buffer_size(&config->offload_info);
4070 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4071 } else {
4072 out->compr_config.fragment_size =
4073 platform_get_compress_offload_buffer_size(&config->offload_info);
4074 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4075 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004076
Amit Shekhar6f461b12014-08-01 14:52:58 -07004077 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304078 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004079
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304080 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4081 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4082 }
4083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4085 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004086
Alexy Josephaa54c872014-12-03 02:46:47 -08004087
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004088 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304089 out->send_next_track_params = false;
4090 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004091 out->offload_state = OFFLOAD_STATE_IDLE;
4092 out->playback_started = 0;
4093
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004094 audio_extn_dts_create_state_notifier_node(out->usecase);
4095
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004096 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4097 __func__, config->offload_info.version,
4098 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304099
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304100 /* Check if DSD audio format is supported in codec
4101 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304102 */
4103
4104 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304105 (!platform_check_codec_dsd_support(adev->platform) ||
4106 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304107 ret = -EINVAL;
4108 goto error_open;
4109 }
4110
Ashish Jain5106d362016-05-11 19:23:33 +05304111 /* Disable gapless if any of the following is true
4112 * passthrough playback
4113 * AV playback
4114 * Direct PCM playback
4115 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304116 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304117 (config->format == AUDIO_FORMAT_DSD) ||
4118 config->offload_info.has_video ||
4119 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304120 check_and_set_gapless_mode(adev, false);
4121 } else
4122 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004123
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304124 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004125 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4126 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304127 if (config->format == AUDIO_FORMAT_DSD) {
4128 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4129 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4130 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004131
4132 create_offload_callback_thread(out);
4133
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004134 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304135 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004136 if (ret != 0) {
4137 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4138 __func__, ret);
4139 goto error_open;
4140 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004141 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4142 if (config->sample_rate == 0)
4143 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4144 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4145 config->sample_rate != 8000) {
4146 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4147 ret = -EINVAL;
4148 goto error_open;
4149 }
4150 out->sample_rate = config->sample_rate;
4151 out->config.rate = config->sample_rate;
4152 if (config->format == AUDIO_FORMAT_DEFAULT)
4153 config->format = AUDIO_FORMAT_PCM_16_BIT;
4154 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4155 config->format = AUDIO_FORMAT_PCM_16_BIT;
4156 ret = -EINVAL;
4157 goto error_open;
4158 }
4159 out->format = config->format;
4160 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4161 out->config = pcm_config_afe_proxy_playback;
4162 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004163 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304164 unsigned int channels = 0;
4165 /*Update config params to default if not set by the caller*/
4166 if (config->sample_rate == 0)
4167 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4168 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4169 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4170 if (config->format == AUDIO_FORMAT_DEFAULT)
4171 config->format = AUDIO_FORMAT_PCM_16_BIT;
4172
4173 channels = audio_channel_count_from_out_mask(out->channel_mask);
4174
Ashish Jain83a6cc22016-06-28 14:34:17 +05304175 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4176 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004177 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4178 out->flags);
4179 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304180 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4181 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4182 out->config = pcm_config_low_latency;
4183 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4184 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4185 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304186 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4187 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4188 if (out->config.period_size <= 0) {
4189 ALOGE("Invalid configuration period size is not valid");
4190 ret = -EINVAL;
4191 goto error_open;
4192 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304193 } else {
4194 /* primary path is the default path selected if no other outputs are available/suitable */
4195 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4196 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4197 }
4198 out->hal_ip_format = format = out->format;
4199 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4200 out->hal_op_format = pcm_format_to_hal(out->config.format);
4201 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4202 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004203 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304204 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304205 if (out->hal_ip_format != out->hal_op_format) {
4206 uint32_t buffer_size = out->config.period_size *
4207 format_to_bitwidth_table[out->hal_op_format] *
4208 out->config.channels;
4209 out->convert_buffer = calloc(1, buffer_size);
4210 if (out->convert_buffer == NULL){
4211 ALOGE("Allocation failed for convert buffer for size %d",
4212 out->compr_config.fragment_size);
4213 ret = -ENOMEM;
4214 goto error_open;
4215 }
4216 ALOGD("Convert buffer allocated of size %d", buffer_size);
4217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 }
4219
Ashish Jain83a6cc22016-06-28 14:34:17 +05304220 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
4221 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
4222
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004223 /* TODO remove this hardcoding and check why width is zero*/
4224 if (out->bit_width == 0)
4225 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304226 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004227 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304228 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304229 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304230 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004231 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4232 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4233 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004234 if(adev->primary_output == NULL)
4235 adev->primary_output = out;
4236 else {
4237 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004238 ret = -EEXIST;
4239 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004240 }
4241 }
4242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 /* Check if this usecase is already existing */
4244 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004245 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4246 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004249 ret = -EEXIST;
4250 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 }
4252 pthread_mutex_unlock(&adev->lock);
4253
4254 out->stream.common.get_sample_rate = out_get_sample_rate;
4255 out->stream.common.set_sample_rate = out_set_sample_rate;
4256 out->stream.common.get_buffer_size = out_get_buffer_size;
4257 out->stream.common.get_channels = out_get_channels;
4258 out->stream.common.get_format = out_get_format;
4259 out->stream.common.set_format = out_set_format;
4260 out->stream.common.standby = out_standby;
4261 out->stream.common.dump = out_dump;
4262 out->stream.common.set_parameters = out_set_parameters;
4263 out->stream.common.get_parameters = out_get_parameters;
4264 out->stream.common.add_audio_effect = out_add_audio_effect;
4265 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4266 out->stream.get_latency = out_get_latency;
4267 out->stream.set_volume = out_set_volume;
4268 out->stream.write = out_write;
4269 out->stream.get_render_position = out_get_render_position;
4270 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004271 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004273 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004275 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004276 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277
4278 config->format = out->stream.common.get_format(&out->stream.common);
4279 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4280 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4281
4282 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304283 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004284 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004285
4286 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4287 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4288 popcount(out->channel_mask), out->playback_started);
4289
Eric Laurent994a6932013-07-17 11:51:42 -07004290 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004292
4293error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304294 if (out->convert_buffer)
4295 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004296 free(out);
4297 *stream_out = NULL;
4298 ALOGD("%s: exit: ret %d", __func__, ret);
4299 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300}
4301
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304302void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004303 struct audio_stream_out *stream)
4304{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004305 struct stream_out *out = (struct stream_out *)stream;
4306 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004307 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004308
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304309 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4310
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004311 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304312 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004313 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304314 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004315 if(ret != 0)
4316 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4317 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004318 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004319 out_standby(&stream->common);
4320
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004321 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004322 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004323 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004324 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004325 if (out->compr_config.codec != NULL)
4326 free(out->compr_config.codec);
4327 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004328
Ashish Jain83a6cc22016-06-28 14:34:17 +05304329 if (out->convert_buffer != NULL) {
4330 free(out->convert_buffer);
4331 out->convert_buffer = NULL;
4332 }
4333
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004334 if (adev->voice_tx_output == out)
4335 adev->voice_tx_output = NULL;
4336
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304337 if (adev->primary_output == out)
4338 adev->primary_output = NULL;
4339
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004340 pthread_cond_destroy(&out->cond);
4341 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004343 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344}
4345
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004346static void close_compress_sessions(struct audio_device *adev)
4347{
Mingming Yin7b762e72015-03-04 13:47:32 -08004348 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304349 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004350 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004351 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304352
4353 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004354 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304355 if (is_offload_usecase(usecase->id)) {
4356 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004357 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4358 out = usecase->stream.out;
4359 pthread_mutex_unlock(&adev->lock);
4360 out_standby(&out->stream.common);
4361 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004362 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004363 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304364 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004365 }
4366 pthread_mutex_unlock(&adev->lock);
4367}
4368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004369static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4370{
4371 struct audio_device *adev = (struct audio_device *)dev;
4372 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004374 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004375 int ret;
4376 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004378 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304381 if (!parms)
4382 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004383 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4384 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304385 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304386 if (strstr(snd_card_status, "OFFLINE")) {
4387 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304388 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004389 //close compress sessions on OFFLINE status
4390 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304391 } else if (strstr(snd_card_status, "ONLINE")) {
4392 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304393 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004394 //send dts hpx license if enabled
4395 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304396 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304397 }
4398
4399 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004400 status = voice_set_parameters(adev, parms);
4401 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004402 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004404 status = platform_set_parameters(adev->platform, parms);
4405 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004406 goto done;
4407
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004408 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4409 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004410 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4412 adev->bluetooth_nrec = true;
4413 else
4414 adev->bluetooth_nrec = false;
4415 }
4416
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004417 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4418 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4420 adev->screen_off = false;
4421 else
4422 adev->screen_off = true;
4423 }
4424
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004425 ret = str_parms_get_int(parms, "rotation", &val);
4426 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004427 bool reverse_speakers = false;
4428 switch(val) {
4429 // FIXME: note that the code below assumes that the speakers are in the correct placement
4430 // relative to the user when the device is rotated 90deg from its default rotation. This
4431 // assumption is device-specific, not platform-specific like this code.
4432 case 270:
4433 reverse_speakers = true;
4434 break;
4435 case 0:
4436 case 90:
4437 case 180:
4438 break;
4439 default:
4440 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004441 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004442 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004443 if (status == 0) {
4444 if (adev->speaker_lr_swap != reverse_speakers) {
4445 adev->speaker_lr_swap = reverse_speakers;
4446 // only update the selected device if there is active pcm playback
4447 struct audio_usecase *usecase;
4448 struct listnode *node;
4449 list_for_each(node, &adev->usecase_list) {
4450 usecase = node_to_item(node, struct audio_usecase, list);
4451 if (usecase->type == PCM_PLAYBACK) {
4452 select_devices(adev, usecase->id);
4453 break;
4454 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004455 }
4456 }
4457 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004458 }
4459
Mingming Yin514a8bc2014-07-29 15:22:21 -07004460 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4461 if (ret >= 0) {
4462 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4463 adev->bt_wb_speech_enabled = true;
4464 else
4465 adev->bt_wb_speech_enabled = false;
4466 }
4467
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004468 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4469 if (ret >= 0) {
4470 val = atoi(value);
4471 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004472 ALOGV("cache new ext disp type and edid");
4473 ret = platform_get_ext_disp_type(adev->platform);
4474 if (ret < 0) {
4475 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004476 status = ret;
4477 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004478 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004479 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004480 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004481 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004482 /*
4483 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4484 * Per AudioPolicyManager, USB device is higher priority than WFD.
4485 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4486 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4487 * starting voice call on USB
4488 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004489 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4490 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004491 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4492 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004493 }
vivek mehta344576a2016-04-12 18:56:03 -07004494 ALOGV("detected USB connect .. disable proxy");
4495 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004496 }
4497 }
4498
4499 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4500 if (ret >= 0) {
4501 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004502 /*
4503 * The HDMI / Displayport disconnect handling has been moved to
4504 * audio extension to ensure that its parameters are not
4505 * invalidated prior to updating sysfs of the disconnect event
4506 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4507 */
4508 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004509 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004510 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4511 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304512 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4513 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004514 }
vivek mehta344576a2016-04-12 18:56:03 -07004515 ALOGV("detected USB disconnect .. enable proxy");
4516 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004517 }
4518 }
4519
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304520 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4521 if (ret >= 0) {
4522 struct audio_usecase *usecase;
4523 struct listnode *node;
4524 list_for_each(node, &adev->usecase_list) {
4525 usecase = node_to_item(node, struct audio_usecase, list);
4526 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004527 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304528 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304529 lock_output_stream(usecase->stream.out);
4530 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304531 //force device switch to re configure encoder
4532 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304533 audio_extn_a2dp_set_handoff_mode(false);
4534 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304535 break;
4536 }
4537 }
4538 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304539 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004540done:
4541 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004542 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304543error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004544 ALOGV("%s: exit with code(%d)", __func__, status);
4545 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546}
4547
4548static char* adev_get_parameters(const struct audio_hw_device *dev,
4549 const char *keys)
4550{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004551 struct audio_device *adev = (struct audio_device *)dev;
4552 struct str_parms *reply = str_parms_create();
4553 struct str_parms *query = str_parms_create_str(keys);
4554 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304555 char value[256] = {0};
4556 int ret = 0;
4557
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004558 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004559 if (reply) {
4560 str_parms_destroy(reply);
4561 }
4562 if (query) {
4563 str_parms_destroy(query);
4564 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004565 ALOGE("adev_get_parameters: failed to create query or reply");
4566 return NULL;
4567 }
4568
Naresh Tannirud7205b62014-06-20 02:54:48 +05304569 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4570 sizeof(value));
4571 if (ret >=0) {
4572 int val = 1;
4573 pthread_mutex_lock(&adev->snd_card_status.lock);
4574 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4575 val = 0;
4576 pthread_mutex_unlock(&adev->snd_card_status.lock);
4577 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4578 goto exit;
4579 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004580
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004581 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004582 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004583 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004584 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304585 pthread_mutex_unlock(&adev->lock);
4586
Naresh Tannirud7205b62014-06-20 02:54:48 +05304587exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004588 str = str_parms_to_str(reply);
4589 str_parms_destroy(query);
4590 str_parms_destroy(reply);
4591
4592 ALOGV("%s: exit: returns - %s", __func__, str);
4593 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594}
4595
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004596static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597{
4598 return 0;
4599}
4600
4601static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4602{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004603 int ret;
4604 struct audio_device *adev = (struct audio_device *)dev;
4605 pthread_mutex_lock(&adev->lock);
4606 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004607 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004608 pthread_mutex_unlock(&adev->lock);
4609 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610}
4611
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004612static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4613 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614{
4615 return -ENOSYS;
4616}
4617
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004618static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4619 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620{
4621 return -ENOSYS;
4622}
4623
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004624static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4625 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626{
4627 return -ENOSYS;
4628}
4629
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004630static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4631 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632{
4633 return -ENOSYS;
4634}
4635
4636static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4637{
4638 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 pthread_mutex_lock(&adev->lock);
4641 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004642 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004644 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004645 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004646 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004647 adev->current_call_output = NULL;
4648 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 }
4650 pthread_mutex_unlock(&adev->lock);
4651 return 0;
4652}
4653
4654static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4655{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004656 int ret;
4657
4658 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004659 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004660 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4661 pthread_mutex_unlock(&adev->lock);
4662
4663 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664}
4665
4666static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4667{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004668 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669 return 0;
4670}
4671
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004672static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004673 const struct audio_config *config)
4674{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004675 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004677 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4678 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679}
4680
4681static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004682 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683 audio_devices_t devices,
4684 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004685 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304686 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004687 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004688 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689{
4690 struct audio_device *adev = (struct audio_device *)dev;
4691 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004692 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004693 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004694 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304695 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304698 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4699 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304701 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702
4703 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004704
4705 if (!in) {
4706 ALOGE("failed to allocate input stream");
4707 return -ENOMEM;
4708 }
4709
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304710 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304711 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4712 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004713 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004714 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716 in->stream.common.get_sample_rate = in_get_sample_rate;
4717 in->stream.common.set_sample_rate = in_set_sample_rate;
4718 in->stream.common.get_buffer_size = in_get_buffer_size;
4719 in->stream.common.get_channels = in_get_channels;
4720 in->stream.common.get_format = in_get_format;
4721 in->stream.common.set_format = in_set_format;
4722 in->stream.common.standby = in_standby;
4723 in->stream.common.dump = in_dump;
4724 in->stream.common.set_parameters = in_set_parameters;
4725 in->stream.common.get_parameters = in_get_parameters;
4726 in->stream.common.add_audio_effect = in_add_audio_effect;
4727 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4728 in->stream.set_gain = in_set_gain;
4729 in->stream.read = in_read;
4730 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4731
4732 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004733 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004734 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004735 in->standby = 1;
4736 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004737 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004738 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304740 in->usecase = USECASE_AUDIO_RECORD;
4741 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4742 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4743 is_low_latency = true;
4744#if LOW_LATENCY_CAPTURE_USE_CASE
4745 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4746#endif
4747 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4748 }
4749
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004750 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004751 if (in->realtime) {
4752 in->config = pcm_config_audio_capture_rt;
4753 in->sample_rate = in->config.rate;
4754 in->af_period_multiplier = af_period_multiplier;
4755 } else {
4756 in->config = pcm_config_audio_capture;
4757 in->config.rate = config->sample_rate;
4758 in->sample_rate = config->sample_rate;
4759 in->af_period_multiplier = 1;
4760 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304761 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304763 /* restrict 24 bit capture for unprocessed source only
4764 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4765 */
4766 if (config->format == AUDIO_FORMAT_DEFAULT) {
4767 config->format = AUDIO_FORMAT_PCM_16_BIT;
4768 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4769 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4770 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4771 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4772 bool ret_error = false;
4773 in->bit_width = 24;
4774 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4775 from HAL is 24_packed and 8_24
4776 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4777 24_packed return error indicating supported format is 24_packed
4778 *> In case of any other source requesting 24 bit or float return error
4779 indicating format supported is 16 bit only.
4780
4781 on error flinger will retry with supported format passed
4782 */
4783 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4784 (source != AUDIO_SOURCE_CAMCORDER)) {
4785 config->format = AUDIO_FORMAT_PCM_16_BIT;
4786 if (config->sample_rate > 48000)
4787 config->sample_rate = 48000;
4788 ret_error = true;
4789 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4790 in->config.format = PCM_FORMAT_S24_3LE;
4791 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4792 in->config.format = PCM_FORMAT_S24_LE;
4793 } else {
4794 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4795 ret_error = true;
4796 }
4797
4798 if (ret_error) {
4799 ret = -EINVAL;
4800 goto err_open;
4801 }
4802 }
4803
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304804 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304805 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4806 (adev->mode != AUDIO_MODE_IN_CALL)) {
4807 ret = -EINVAL;
4808 goto err_open;
4809 }
4810
4811 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4812 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004813 if (config->sample_rate == 0)
4814 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4815 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4816 config->sample_rate != 8000) {
4817 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4818 ret = -EINVAL;
4819 goto err_open;
4820 }
4821 if (config->format == AUDIO_FORMAT_DEFAULT)
4822 config->format = AUDIO_FORMAT_PCM_16_BIT;
4823 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4824 config->format = AUDIO_FORMAT_PCM_16_BIT;
4825 ret = -EINVAL;
4826 goto err_open;
4827 }
4828
4829 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4830 in->config = pcm_config_afe_proxy_record;
4831 in->config.channels = channel_count;
4832 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304833 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304834 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4835 in, config, &channel_mask_updated)) {
4836 if (channel_mask_updated == true) {
4837 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4838 __func__, config->channel_mask);
4839 ret = -EINVAL;
4840 goto err_open;
4841 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304842 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004843 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004844 audio_extn_compr_cap_format_supported(config->format) &&
4845 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004846 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304847 } else if (audio_extn_cin_applicable_stream(in)) {
4848 ret = audio_extn_cin_configure_input_stream(in);
4849 if (ret)
4850 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004851 } else {
4852 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004853 if (!in->realtime) {
4854 in->format = config->format;
4855 frame_size = audio_stream_in_frame_size(&in->stream);
4856 buffer_size = get_input_buffer_size(config->sample_rate,
4857 config->format,
4858 channel_count,
4859 is_low_latency);
4860 in->config.period_size = buffer_size / frame_size;
4861 }
4862
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004863 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004864 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004865 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004866 (in->config.rate == 8000 || in->config.rate == 16000 ||
4867 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004868 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4869 voice_extn_compress_voip_open_input_stream(in);
4870 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004872
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304873 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4874 &adev->streams_input_cfg_list,
4875 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304876 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304877
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004878 /* This stream could be for sound trigger lab,
4879 get sound trigger pcm if present */
4880 audio_extn_sound_trigger_check_and_get_session(in);
4881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004882 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004883 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004884 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885
4886err_open:
4887 free(in);
4888 *stream_in = NULL;
4889 return ret;
4890}
4891
4892static void adev_close_input_stream(struct audio_hw_device *dev,
4893 struct audio_stream_in *stream)
4894{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004895 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004896 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004897 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304898
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304899 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004900
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304901 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004902 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304903
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004904 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304905 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004906 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304907 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004908 if (ret != 0)
4909 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4910 __func__, ret);
4911 } else
4912 in_standby(&stream->common);
4913
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004914 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004915 audio_extn_ssr_deinit();
4916 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304918 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07004919 audio_extn_compr_cap_format_supported(in->config.format))
4920 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304921
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304922 if (audio_extn_cin_attached_usecase(in->usecase))
4923 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004924
Mingming Yinfd7607b2016-01-22 12:48:44 -08004925 if (in->is_st_session) {
4926 ALOGV("%s: sound trigger pcm stop lab", __func__);
4927 audio_extn_sound_trigger_stop_lab(in);
4928 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004929 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930 return;
4931}
4932
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004933static int adev_dump(const audio_hw_device_t *device __unused,
4934 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004935{
4936 return 0;
4937}
4938
4939static int adev_close(hw_device_t *device)
4940{
4941 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004942
4943 if (!adev)
4944 return 0;
4945
4946 pthread_mutex_lock(&adev_init_lock);
4947
4948 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004949 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004950 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304951 audio_extn_utils_release_streams_cfg_lists(
4952 &adev->streams_output_cfg_list,
4953 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304954 if (audio_extn_qaf_is_enabled())
4955 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004956 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08004957 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07004958 free(adev->snd_dev_ref_cnt);
4959 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004960 if (adev->adm_deinit)
4961 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304962 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07004963 free(device);
4964 adev = NULL;
4965 }
4966 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968 return 0;
4969}
4970
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004971/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4972 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4973 * just that it _might_ work.
4974 */
4975static int period_size_is_plausible_for_low_latency(int period_size)
4976{
4977 switch (period_size) {
4978 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004979 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004980 case 240:
4981 case 320:
4982 case 480:
4983 return 1;
4984 default:
4985 return 0;
4986 }
4987}
4988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989static int adev_open(const hw_module_t *module, const char *name,
4990 hw_device_t **device)
4991{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304992 int ret;
4993
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004994 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004995 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4996
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004997 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004998 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004999 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005000 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005001 ALOGD("%s: returning existing instance of adev", __func__);
5002 ALOGD("%s: exit", __func__);
5003 pthread_mutex_unlock(&adev_init_lock);
5004 return 0;
5005 }
5006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007 adev = calloc(1, sizeof(struct audio_device));
5008
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005009 if (!adev) {
5010 pthread_mutex_unlock(&adev_init_lock);
5011 return -ENOMEM;
5012 }
5013
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005014 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005016 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5017 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5018 adev->device.common.module = (struct hw_module_t *)module;
5019 adev->device.common.close = adev_close;
5020
5021 adev->device.init_check = adev_init_check;
5022 adev->device.set_voice_volume = adev_set_voice_volume;
5023 adev->device.set_master_volume = adev_set_master_volume;
5024 adev->device.get_master_volume = adev_get_master_volume;
5025 adev->device.set_master_mute = adev_set_master_mute;
5026 adev->device.get_master_mute = adev_get_master_mute;
5027 adev->device.set_mode = adev_set_mode;
5028 adev->device.set_mic_mute = adev_set_mic_mute;
5029 adev->device.get_mic_mute = adev_get_mic_mute;
5030 adev->device.set_parameters = adev_set_parameters;
5031 adev->device.get_parameters = adev_get_parameters;
5032 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5033 adev->device.open_output_stream = adev_open_output_stream;
5034 adev->device.close_output_stream = adev_close_output_stream;
5035 adev->device.open_input_stream = adev_open_input_stream;
5036 adev->device.close_input_stream = adev_close_input_stream;
5037 adev->device.dump = adev_dump;
5038
5039 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005041 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005042 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005045 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005046 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005047 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005048 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005049 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005050 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005051 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005052 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305053 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305054 adev->perf_lock_opts[0] = 0x101;
5055 adev->perf_lock_opts[1] = 0x20E;
5056 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305057
5058 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5059 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005060 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005061 adev->platform = platform_init(adev);
5062 if (!adev->platform) {
5063 free(adev->snd_dev_ref_cnt);
5064 free(adev);
5065 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5066 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005067 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305068 pthread_mutex_destroy(&adev->lock);
5069 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005070 return -EINVAL;
5071 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005072
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305073 if (audio_extn_qaf_is_enabled()) {
5074 ret = audio_extn_qaf_init(adev);
5075 if (ret < 0) {
5076 free(adev);
5077 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5078 *device = NULL;
5079 pthread_mutex_unlock(&adev_init_lock);
5080 pthread_mutex_destroy(&adev->lock);
5081 return ret;
5082 }
5083
5084 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5085 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5086 }
5087
Naresh Tanniru4c630392014-05-12 01:05:52 +05305088 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5089
Eric Laurentc4aef752013-09-12 17:45:53 -07005090 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5091 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5092 if (adev->visualizer_lib == NULL) {
5093 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5094 } else {
5095 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5096 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005097 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005098 "visualizer_hal_start_output");
5099 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005100 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005101 "visualizer_hal_stop_output");
5102 }
5103 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305104 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005105 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005106 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005107 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005108
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005109 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5110 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5111 if (adev->offload_effects_lib == NULL) {
5112 ALOGE("%s: DLOPEN failed for %s", __func__,
5113 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5114 } else {
5115 ALOGV("%s: DLOPEN successful for %s", __func__,
5116 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5117 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305118 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005119 "offload_effects_bundle_hal_start_output");
5120 adev->offload_effects_stop_output =
5121 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5122 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005123 adev->offload_effects_set_hpx_state =
5124 (int (*)(bool))dlsym(adev->offload_effects_lib,
5125 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305126 adev->offload_effects_get_parameters =
5127 (void (*)(struct str_parms *, struct str_parms *))
5128 dlsym(adev->offload_effects_lib,
5129 "offload_effects_bundle_get_parameters");
5130 adev->offload_effects_set_parameters =
5131 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5132 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005133 }
5134 }
5135
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005136 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5137 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5138 if (adev->adm_lib == NULL) {
5139 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5140 } else {
5141 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5142 adev->adm_init = (adm_init_t)
5143 dlsym(adev->adm_lib, "adm_init");
5144 adev->adm_deinit = (adm_deinit_t)
5145 dlsym(adev->adm_lib, "adm_deinit");
5146 adev->adm_register_input_stream = (adm_register_input_stream_t)
5147 dlsym(adev->adm_lib, "adm_register_input_stream");
5148 adev->adm_register_output_stream = (adm_register_output_stream_t)
5149 dlsym(adev->adm_lib, "adm_register_output_stream");
5150 adev->adm_deregister_stream = (adm_deregister_stream_t)
5151 dlsym(adev->adm_lib, "adm_deregister_stream");
5152 adev->adm_request_focus = (adm_request_focus_t)
5153 dlsym(adev->adm_lib, "adm_request_focus");
5154 adev->adm_abandon_focus = (adm_abandon_focus_t)
5155 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005156 adev->adm_set_config = (adm_set_config_t)
5157 dlsym(adev->adm_lib, "adm_set_config");
5158 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5159 dlsym(adev->adm_lib, "adm_request_focus_v2");
5160 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5161 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5162 adev->adm_on_routing_change = (adm_on_routing_change_t)
5163 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005164 }
5165 }
5166
Mingming Yin514a8bc2014-07-29 15:22:21 -07005167 adev->bt_wb_speech_enabled = false;
5168
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005169 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005170 *device = &adev->device.common;
5171
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305172 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5173 &adev->streams_output_cfg_list,
5174 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005175
Kiran Kandi910e1862013-10-29 13:29:42 -07005176 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005177
5178 char value[PROPERTY_VALUE_MAX];
5179 int trial;
5180 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5181 trial = atoi(value);
5182 if (period_size_is_plausible_for_low_latency(trial)) {
5183 pcm_config_low_latency.period_size = trial;
5184 pcm_config_low_latency.start_threshold = trial / 4;
5185 pcm_config_low_latency.avail_min = trial / 4;
5186 configured_low_latency_capture_period_size = trial;
5187 }
5188 }
5189 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5190 trial = atoi(value);
5191 if (period_size_is_plausible_for_low_latency(trial)) {
5192 configured_low_latency_capture_period_size = trial;
5193 }
5194 }
5195
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005196 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5197 af_period_multiplier = atoi(value);
5198 if (af_period_multiplier < 0)
5199 af_period_multiplier = 2;
5200 else if (af_period_multiplier > 4)
5201 af_period_multiplier = 4;
5202
5203 ALOGV("new period_multiplier = %d", af_period_multiplier);
5204 }
5205
vivek mehta446c3962015-09-14 10:57:35 -07005206 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005207 pthread_mutex_unlock(&adev_init_lock);
5208
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005209 if (adev->adm_init)
5210 adev->adm_data = adev->adm_init();
5211
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305212 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305213 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005214 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005215 return 0;
5216}
5217
5218static struct hw_module_methods_t hal_module_methods = {
5219 .open = adev_open,
5220};
5221
5222struct audio_module HAL_MODULE_INFO_SYM = {
5223 .common = {
5224 .tag = HARDWARE_MODULE_TAG,
5225 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5226 .hal_api_version = HARDWARE_HAL_API_VERSION,
5227 .id = AUDIO_HARDWARE_MODULE_ID,
5228 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005229 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230 .methods = &hal_module_methods,
5231 },
5232};