blob: 498bab7e06462cfe415961c984ff6d06f304b8c9 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002 * Copyright (c) 2013-2016, 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
85
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070086#define PROXY_OPEN_RETRY_COUNT 100
87#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080088
Mingming Yin08c7e312015-03-16 18:10:58 -070089#ifdef USE_LL_AS_PRIMARY_OUTPUT
90#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
91#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
92#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080093#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070094#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
95#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080096
Haynes Mathew George5beddd42016-06-27 18:33:40 -070097#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
98
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070099static unsigned int configured_low_latency_capture_period_size =
100 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
101
Eric Laurentb23d5282013-05-14 15:27:20 -0700102struct pcm_config pcm_config_deep_buffer = {
103 .channels = 2,
104 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
105 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
106 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
107 .format = PCM_FORMAT_S16_LE,
108 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
109 .stop_threshold = INT_MAX,
110 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
111};
112
113struct pcm_config pcm_config_low_latency = {
114 .channels = 2,
115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
117 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
122};
123
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700124static int af_period_multiplier = 4;
125struct pcm_config pcm_config_rt = {
126 .channels = 2,
127 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
128 .period_size = ULL_PERIOD_SIZE, //1 ms
129 .period_count = 512, //=> buffer size is 512ms
130 .format = PCM_FORMAT_S16_LE,
131 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
132 .stop_threshold = INT_MAX,
133 .silence_threshold = 0,
134 .silence_size = 0,
135 .avail_min = ULL_PERIOD_SIZE, //1 ms
136};
137
Eric Laurentb23d5282013-05-14 15:27:20 -0700138struct pcm_config pcm_config_hdmi_multi = {
139 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
140 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
141 .period_size = HDMI_MULTI_PERIOD_SIZE,
142 .period_count = HDMI_MULTI_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = 0,
145 .stop_threshold = INT_MAX,
146 .avail_min = 0,
147};
148
149struct pcm_config pcm_config_audio_capture = {
150 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700151 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
152 .format = PCM_FORMAT_S16_LE,
153};
154
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700155struct pcm_config pcm_config_audio_capture_rt = {
156 .channels = 2,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = ULL_PERIOD_SIZE,
159 .period_count = 512,
160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = 0,
162 .stop_threshold = INT_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = ULL_PERIOD_SIZE, //1 ms
166};
167
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700168#define AFE_PROXY_CHANNEL_COUNT 2
169#define AFE_PROXY_SAMPLING_RATE 48000
170
171#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
172#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
173
174struct pcm_config pcm_config_afe_proxy_playback = {
175 .channels = AFE_PROXY_CHANNEL_COUNT,
176 .rate = AFE_PROXY_SAMPLING_RATE,
177 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
178 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
179 .format = PCM_FORMAT_S16_LE,
180 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
181 .stop_threshold = INT_MAX,
182 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
183};
184
185#define AFE_PROXY_RECORD_PERIOD_SIZE 768
186#define AFE_PROXY_RECORD_PERIOD_COUNT 4
187
188struct pcm_config pcm_config_afe_proxy_record = {
189 .channels = AFE_PROXY_CHANNEL_COUNT,
190 .rate = AFE_PROXY_SAMPLING_RATE,
191 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
192 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
193 .format = PCM_FORMAT_S16_LE,
194 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
195 .stop_threshold = INT_MAX,
196 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
197};
198
Ashish Jainf1eaa582016-05-23 20:54:24 +0530199#define AUDIO_MAX_PCM_FORMATS 7
200
201const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
202 [AUDIO_FORMAT_DEFAULT] = 0,
203 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
204 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
205 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
206 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
207 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
208 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
209};
210
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800211const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700212 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
213 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700214 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
215 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700216 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700217 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700218 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
219 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700226
Eric Laurentb23d5282013-05-14 15:27:20 -0700227 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700228 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700229 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700230 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700231 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800232 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800233 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700234 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700235
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700236 [USECASE_VOICE2_CALL] = "voice2-call",
237 [USECASE_VOLTE_CALL] = "volte-call",
238 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800239 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800240 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
241 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800242 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700243 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
244 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
245 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800246 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
247 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
248 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
249
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700250 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
251 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700252 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
253 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700254
255 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
256 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700257};
258
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700259static const audio_usecase_t offload_usecases[] = {
260 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700261 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
262 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
263 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
264 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700269};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800270
271#define STRING_TO_ENUM(string) { #string, string }
272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800273struct string_to_enum {
274 const char *name;
275 uint32_t value;
276};
277
278static const struct string_to_enum out_channels_name_to_enum_table[] = {
279 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800280 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
281 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
287};
288
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700289static const struct string_to_enum out_formats_name_to_enum_table[] = {
290 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
291 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
292 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800293 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
294 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
295};
296
297//list of all supported sample rates by HDMI specification.
298static const int out_hdmi_sample_rates[] = {
299 32000, 44100, 48000, 88200, 96000, 176400, 192000,
300};
301
302static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
303 STRING_TO_ENUM(32000),
304 STRING_TO_ENUM(44100),
305 STRING_TO_ENUM(48000),
306 STRING_TO_ENUM(88200),
307 STRING_TO_ENUM(96000),
308 STRING_TO_ENUM(176400),
309 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700310};
311
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700312static struct audio_device *adev = NULL;
313static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700314static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700315//cache last MBDRC cal step level
316static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700317
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700318static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
319 int flags __unused)
320{
321 int dir = 0;
322 switch (uc_id) {
323 case USECASE_AUDIO_RECORD_LOW_LATENCY:
324 dir = 1;
325 case USECASE_AUDIO_PLAYBACK_ULL:
326 break;
327 default:
328 return false;
329 }
330
331 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
332 PCM_PLAYBACK : PCM_CAPTURE);
333 if (adev->adm_is_noirq_avail)
334 return adev->adm_is_noirq_avail(adev->adm_data,
335 adev->snd_card, dev_id, dir);
336 return false;
337}
338
339static void register_out_stream(struct stream_out *out)
340{
341 struct audio_device *adev = out->dev;
342 if (is_offload_usecase(out->usecase) ||
343 !adev->adm_register_output_stream)
344 return;
345
346 // register stream first for backward compatibility
347 adev->adm_register_output_stream(adev->adm_data,
348 out->handle,
349 out->flags);
350
351 if (!adev->adm_set_config)
352 return;
353
354 if (out->realtime)
355 adev->adm_set_config(adev->adm_data,
356 out->handle,
357 out->pcm, &out->config);
358}
359
360static void register_in_stream(struct stream_in *in)
361{
362 struct audio_device *adev = in->dev;
363 if (!adev->adm_register_input_stream)
364 return;
365
366 adev->adm_register_input_stream(adev->adm_data,
367 in->capture_handle,
368 in->flags);
369
370 if (!adev->adm_set_config)
371 return;
372
373 if (in->realtime)
374 adev->adm_set_config(adev->adm_data,
375 in->capture_handle,
376 in->pcm,
377 &in->config);
378}
379
380static void request_out_focus(struct stream_out *out, long ns)
381{
382 struct audio_device *adev = out->dev;
383
384 if (out->routing_change) {
385 out->routing_change = false;
386 // must be checked for backward compatibility
387 if (adev->adm_on_routing_change)
388 adev->adm_on_routing_change(adev->adm_data, out->handle);
389 }
390
391 if (adev->adm_request_focus_v2)
392 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
393 else if (adev->adm_request_focus)
394 adev->adm_request_focus(adev->adm_data, out->handle);
395}
396
397static void request_in_focus(struct stream_in *in, long ns)
398{
399 struct audio_device *adev = in->dev;
400
401 if (in->routing_change) {
402 in->routing_change = false;
403 if (adev->adm_on_routing_change)
404 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
405 }
406
407 if (adev->adm_request_focus_v2)
408 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
409 else if (adev->adm_request_focus)
410 adev->adm_request_focus(adev->adm_data, in->capture_handle);
411}
412
413static void release_out_focus(struct stream_out *out)
414{
415 struct audio_device *adev = out->dev;
416
417 if (adev->adm_abandon_focus)
418 adev->adm_abandon_focus(adev->adm_data, out->handle);
419}
420
421static void release_in_focus(struct stream_in *in)
422{
423 struct audio_device *adev = in->dev;
424 if (adev->adm_abandon_focus)
425 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
426}
427
vivek mehtaa76401a2015-04-24 14:12:15 -0700428__attribute__ ((visibility ("default")))
429bool audio_hw_send_gain_dep_calibration(int level) {
430 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700431 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700432
433 pthread_mutex_lock(&adev_init_lock);
434
435 if (adev != NULL && adev->platform != NULL) {
436 pthread_mutex_lock(&adev->lock);
437 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700438
439 // if cal set fails, cache level info
440 // if cal set succeds, reset known last cal set
441 if (!ret_val)
442 last_known_cal_step = level;
443 else if (last_known_cal_step != -1)
444 last_known_cal_step = -1;
445
vivek mehtaa76401a2015-04-24 14:12:15 -0700446 pthread_mutex_unlock(&adev->lock);
447 } else {
448 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
449 }
450
451 pthread_mutex_unlock(&adev_init_lock);
452
453 return ret_val;
454}
455
Ashish Jain5106d362016-05-11 19:23:33 +0530456static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
457{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800458 bool gapless_enabled = false;
459 const char *mixer_ctl_name = "Compress Gapless Playback";
460 struct mixer_ctl *ctl;
461
462 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530463 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
464
465 /*Disable gapless if its AV playback*/
466 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800467
468 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
469 if (!ctl) {
470 ALOGE("%s: Could not get ctl for mixer cmd - %s",
471 __func__, mixer_ctl_name);
472 return -EINVAL;
473 }
474
475 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
476 ALOGE("%s: Could not set gapless mode %d",
477 __func__, gapless_enabled);
478 return -EINVAL;
479 }
480 return 0;
481}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700482
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700483static bool is_supported_format(audio_format_t format)
484{
Eric Laurent86e17132013-09-12 17:49:30 -0700485 if (format == AUDIO_FORMAT_MP3 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530486 format == AUDIO_FORMAT_AAC_LC ||
487 format == AUDIO_FORMAT_AAC_HE_V1 ||
488 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530489 format == AUDIO_FORMAT_AAC_ADTS_LC ||
490 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
491 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530492 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
493 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530494 format == AUDIO_FORMAT_PCM_FLOAT ||
495 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700496 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530497 format == AUDIO_FORMAT_AC3 ||
498 format == AUDIO_FORMAT_E_AC3 ||
499 format == AUDIO_FORMAT_DTS ||
500 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800501 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530502 format == AUDIO_FORMAT_ALAC ||
503 format == AUDIO_FORMAT_APE ||
504 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800505 format == AUDIO_FORMAT_WMA ||
506 format == AUDIO_FORMAT_WMA_PRO)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800507 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700508
509 return false;
510}
511
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700512static inline bool is_mmap_usecase(audio_usecase_t uc_id)
513{
514 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
515 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
516}
517
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700518static int get_snd_codec_id(audio_format_t format)
519{
520 int id = 0;
521
Ashish Jainf9b78162014-08-25 20:36:25 +0530522 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700523 case AUDIO_FORMAT_MP3:
524 id = SND_AUDIOCODEC_MP3;
525 break;
526 case AUDIO_FORMAT_AAC:
527 id = SND_AUDIOCODEC_AAC;
528 break;
Manish Dewangana6fc5442015-08-24 20:30:31 +0530529 case AUDIO_FORMAT_AAC_ADTS:
530 id = SND_AUDIOCODEC_AAC;
531 break;
vivek mehta0ea887a2015-08-26 14:01:20 -0700532 case AUDIO_FORMAT_PCM:
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800533 id = SND_AUDIOCODEC_PCM;
534 break;
Mingming Yin3ee55c62014-08-04 14:23:35 -0700535 case AUDIO_FORMAT_FLAC:
536 id = SND_AUDIOCODEC_FLAC;
537 break;
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530538 case AUDIO_FORMAT_ALAC:
539 id = SND_AUDIOCODEC_ALAC;
540 break;
541 case AUDIO_FORMAT_APE:
542 id = SND_AUDIOCODEC_APE;
543 break;
544 case AUDIO_FORMAT_VORBIS:
545 id = SND_AUDIOCODEC_VORBIS;
546 break;
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800547 case AUDIO_FORMAT_WMA:
548 id = SND_AUDIOCODEC_WMA;
549 break;
550 case AUDIO_FORMAT_WMA_PRO:
551 id = SND_AUDIOCODEC_WMA_PRO;
552 break;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530553 case AUDIO_FORMAT_AC3:
554 id = SND_AUDIOCODEC_AC3;
555 break;
556 case AUDIO_FORMAT_E_AC3:
557 case AUDIO_FORMAT_E_AC3_JOC:
558 id = SND_AUDIOCODEC_EAC3;
559 break;
560 case AUDIO_FORMAT_DTS:
561 case AUDIO_FORMAT_DTS_HD:
562 id = SND_AUDIOCODEC_DTS;
563 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700564 default:
Mingming Yin90310102013-11-13 16:57:00 -0800565 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700566 }
567
568 return id;
569}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800570
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530571int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530572{
573 int snd_scard_state;
574
575 if (!adev)
576 return SND_CARD_STATE_OFFLINE;
577
578 pthread_mutex_lock(&adev->snd_card_status.lock);
579 snd_scard_state = adev->snd_card_status.state;
580 pthread_mutex_unlock(&adev->snd_card_status.lock);
581
582 return snd_scard_state;
583}
584
585static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
586{
587 if (!adev)
588 return -ENOSYS;
589
590 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700591 if (adev->snd_card_status.state != snd_scard_state) {
592 adev->snd_card_status.state = snd_scard_state;
593 platform_snd_card_update(adev->platform, snd_scard_state);
594 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530595 pthread_mutex_unlock(&adev->snd_card_status.lock);
596
597 return 0;
598}
599
Avinash Vaish71a8b972014-07-24 15:36:33 +0530600static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
601 struct audio_usecase *uc_info)
602{
603 struct listnode *node;
604 struct audio_usecase *usecase;
605
606 if (uc_info == NULL)
607 return -EINVAL;
608
609 /* Re-route all voice usecases on the shared backend other than the
610 specified usecase to new snd devices */
611 list_for_each(node, &adev->usecase_list) {
612 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800613 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530614 enable_audio_route(adev, usecase);
615 }
616 return 0;
617}
618
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700619int pcm_ioctl(struct pcm *pcm, int request, ...)
620{
621 va_list ap;
622 void * arg;
623 int pcm_fd = *(int*)pcm;
624
625 va_start(ap, request);
626 arg = va_arg(ap, void *);
627 va_end(ap);
628
629 return ioctl(pcm_fd, request, arg);
630}
631
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700632int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700633 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800634{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700636 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800637
638 if (usecase == NULL)
639 return -EINVAL;
640
641 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
642
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800643 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700644 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800645 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700646 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800647
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800648#ifdef DS1_DOLBY_DAP_ENABLED
649 audio_extn_dolby_set_dmid(adev);
650 audio_extn_dolby_set_endpoint(adev);
651#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700652 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700653 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530654 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700655 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530656 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800657 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700658 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700659 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700660 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800661 ALOGV("%s: exit", __func__);
662 return 0;
663}
664
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700665int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700666 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800667{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700668 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700669 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800670
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530671 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800672 return -EINVAL;
673
674 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 if (usecase->type == PCM_CAPTURE)
676 snd_device = usecase->in_snd_device;
677 else
678 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800679 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700680 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700681 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700682 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700683 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530684 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800685 ALOGV("%s: exit", __func__);
686 return 0;
687}
688
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700689int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700690 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800691{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530692 int i, num_devices = 0;
693 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700694 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
695
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800696 if (snd_device < SND_DEVICE_MIN ||
697 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800698 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800699 return -EINVAL;
700 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700701
702 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700703
704 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
705 ALOGE("%s: Invalid sound device returned", __func__);
706 return -EINVAL;
707 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700708 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700709 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700710 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 return 0;
712 }
713
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530714
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700715 if (audio_extn_spkr_prot_is_enabled())
716 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700717
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700718
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800719 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
720 audio_extn_spkr_prot_is_enabled()) {
721 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700722 adev->snd_dev_ref_cnt[snd_device]--;
723 return -EINVAL;
724 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200725 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800726 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800727 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200728 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800729 return -EINVAL;
730 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530731 } else if (platform_can_split_snd_device(adev->platform, snd_device,
732 &num_devices, new_snd_devices)) {
733 for (i = 0; i < num_devices; i++) {
734 enable_snd_device(adev, new_snd_devices[i]);
735 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800736 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700737 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700738 /* due to the possibility of calibration overwrite between listen
739 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700740 audio_extn_sound_trigger_update_device_status(snd_device,
741 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530742 audio_extn_listen_update_device_status(snd_device,
743 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700744 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700745 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700746 audio_extn_sound_trigger_update_device_status(snd_device,
747 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530748 audio_extn_listen_update_device_status(snd_device,
749 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700750 return -EINVAL;
751 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300752 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700753 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530754
755 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
756 !adev->native_playback_enabled &&
757 audio_is_true_native_stream_active(adev)) {
758 ALOGD("%s: %d: napb: enabling native mode in hardware",
759 __func__, __LINE__);
760 audio_route_apply_and_update_path(adev->audio_route,
761 "true-native-mode");
762 adev->native_playback_enabled = true;
763 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800764 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765 return 0;
766}
767
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700768int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700769 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530771 int i, num_devices = 0;
772 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700773 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
774
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800775 if (snd_device < SND_DEVICE_MIN ||
776 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800777 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800778 return -EINVAL;
779 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700780 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
781 ALOGE("%s: device ref cnt is already 0", __func__);
782 return -EINVAL;
783 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700784
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700785 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700786
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700787 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
788 ALOGE("%s: Invalid sound device returned", __func__);
789 return -EINVAL;
790 }
791
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700793 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800794 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
795 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700796 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530797 } else if (platform_can_split_snd_device(adev->platform, snd_device,
798 &num_devices, new_snd_devices)) {
799 for (i = 0; i < num_devices; i++) {
800 disable_snd_device(adev, new_snd_devices[i]);
801 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300802 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700803 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300804 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700805
Ashish Jain81eb2a82015-05-13 10:52:34 +0530806 if (snd_device == SND_DEVICE_OUT_HDMI)
807 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530808 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
809 adev->native_playback_enabled) {
810 ALOGD("%s: %d: napb: disabling native mode in hardware",
811 __func__, __LINE__);
812 audio_route_reset_and_update_path(adev->audio_route,
813 "true-native-mode");
814 adev->native_playback_enabled = false;
815 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530816
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200817 audio_extn_dev_arbi_release(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,
Kiran Kandide144c82013-11-20 15:58:32 -0800821 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700822 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800824 return 0;
825}
826
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530828 struct audio_usecase *uc_info,
829 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830{
831 struct listnode *node;
832 struct audio_usecase *usecase;
833 bool switch_device[AUDIO_USECASE_MAX];
834 int i, num_uc_to_switch = 0;
835
836 /*
837 * This function is to make sure that all the usecases that are active on
838 * the hardware codec backend are always routed to any one device that is
839 * handled by the hardware codec.
840 * For example, if low-latency and deep-buffer usecases are currently active
841 * on speaker and out_set_parameters(headset) is received on low-latency
842 * output, then we have to make sure deep-buffer is also switched to headset,
843 * because of the limitation that both the devices cannot be enabled
844 * at the same time as they share the same backend.
845 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700846 /*
847 * This call is to check if we need to force routing for a particular stream
848 * If there is a backend configuration change for the device when a
849 * new stream starts, then ADM needs to be closed and re-opened with the new
850 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800851 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700852 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800853 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
854 snd_device);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530855
856 ALOGD("%s:becf: force routing %d", __func__, force_routing);
857
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700858 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800859 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800860 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 for (i = 0; i < AUDIO_USECASE_MAX; i++)
862 switch_device[i] = false;
863
864 list_for_each(node, &adev->usecase_list) {
865 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800866
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530867 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
868 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530869 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530870 platform_get_snd_device_name(usecase->out_snd_device),
871 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800872 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530873 usecase != uc_info &&
874 (usecase->out_snd_device != snd_device || force_routing) &&
875 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
876 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
877 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
878 __func__, use_case_table[usecase->id],
879 platform_get_snd_device_name(usecase->out_snd_device));
880 disable_audio_route(adev, usecase);
881 switch_device[usecase->id] = true;
882 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 }
884 }
885
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530886 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
887 num_uc_to_switch);
888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700890 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530892 /* Make sure the previous devices to be disabled first and then enable the
893 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 list_for_each(node, &adev->usecase_list) {
895 usecase = node_to_item(node, struct audio_usecase, list);
896 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700897 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 }
900
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700901 list_for_each(node, &adev->usecase_list) {
902 usecase = node_to_item(node, struct audio_usecase, list);
903 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700904 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700905 }
906 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 /* Re-route all the usecases on the shared backend other than the
909 specified usecase to new snd devices */
910 list_for_each(node, &adev->usecase_list) {
911 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530912 /* Update the out_snd_device only before enabling the audio route */
913 if (switch_device[usecase->id]) {
914 usecase->out_snd_device = snd_device;
915 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530916 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530917 use_case_table[usecase->id],
918 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530919 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530920 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921 }
922 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923 }
924}
925
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530926static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700927 struct audio_usecase *uc_info,
928 snd_device_t snd_device)
929{
930 struct listnode *node;
931 struct audio_usecase *usecase;
932 bool switch_device[AUDIO_USECASE_MAX];
933 int i, num_uc_to_switch = 0;
934
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530935 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
936 snd_device);
937 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 /*
939 * This function is to make sure that all the active capture usecases
940 * are always routed to the same input sound device.
941 * For example, if audio-record and voice-call usecases are currently
942 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
943 * is received for voice call then we have to make sure that audio-record
944 * usecase is also switched to earpiece i.e. voice-dmic-ef,
945 * because of the limitation that two devices cannot be enabled
946 * at the same time if they share the same backend.
947 */
948 for (i = 0; i < AUDIO_USECASE_MAX; i++)
949 switch_device[i] = false;
950
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800953 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700954 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530955 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700956 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530957 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +0800958 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700959 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700960 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
961 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700962 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700963 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700964 switch_device[usecase->id] = true;
965 num_uc_to_switch++;
966 }
967 }
968
969 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700970 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700971
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530972 /* Make sure the previous devices to be disabled first and then enable the
973 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 list_for_each(node, &adev->usecase_list) {
975 usecase = node_to_item(node, struct audio_usecase, list);
976 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700977 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800978 }
979 }
980
981 list_for_each(node, &adev->usecase_list) {
982 usecase = node_to_item(node, struct audio_usecase, list);
983 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700984 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700985 }
986 }
987
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700988 /* Re-route all the usecases on the shared backend other than the
989 specified usecase to new snd devices */
990 list_for_each(node, &adev->usecase_list) {
991 usecase = node_to_item(node, struct audio_usecase, list);
992 /* Update the in_snd_device only before enabling the audio route */
993 if (switch_device[usecase->id] ) {
994 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800995 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +0530996 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700997 }
998 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700999 }
1000}
1001
Mingming Yin3a941d42016-02-17 18:08:05 -08001002static void reset_hdmi_sink_caps(struct stream_out *out) {
1003 int i = 0;
1004
1005 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1006 out->supported_channel_masks[i] = 0;
1007 }
1008 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1009 out->supported_formats[i] = 0;
1010 }
1011 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1012 out->supported_sample_rates[i] = 0;
1013 }
1014}
1015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001017static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018{
Mingming Yin3a941d42016-02-17 18:08:05 -08001019 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001020 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021
Mingming Yin3a941d42016-02-17 18:08:05 -08001022 reset_hdmi_sink_caps(out);
1023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001026 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001027 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001028 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1029 case 6:
1030 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1031 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1032 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1033 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1034 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1035 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001036 break;
1037 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001038 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001039 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040 break;
1041 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001042
1043 // check channel format caps
1044 i = 0;
1045 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1046 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1047 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1048 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1049 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1050 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1051 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1052 }
1053
1054 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1055 ALOGV(":%s HDMI supports DTS format", __func__);
1056 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1057 }
1058
1059 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1060 ALOGV(":%s HDMI supports DTS HD format", __func__);
1061 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1062 }
1063
1064
1065 // check sample rate caps
1066 i = 0;
1067 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1068 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1069 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1070 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1071 }
1072 }
1073
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075}
1076
Alexy Josephb1379942016-01-29 15:49:38 -08001077audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001078 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001079{
1080 struct audio_usecase *usecase;
1081 struct listnode *node;
1082
1083 list_for_each(node, &adev->usecase_list) {
1084 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001085 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001086 ALOGV("%s: usecase id %d", __func__, usecase->id);
1087 return usecase->id;
1088 }
1089 }
1090 return USECASE_INVALID;
1091}
1092
Alexy Josephb1379942016-01-29 15:49:38 -08001093struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001094 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095{
1096 struct audio_usecase *usecase;
1097 struct listnode *node;
1098
1099 list_for_each(node, &adev->usecase_list) {
1100 usecase = node_to_item(node, struct audio_usecase, list);
1101 if (usecase->id == uc_id)
1102 return usecase;
1103 }
1104 return NULL;
1105}
1106
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301107/*
1108 * is a true native playback active
1109 */
1110bool audio_is_true_native_stream_active(struct audio_device *adev)
1111{
1112 bool active = false;
1113 int i = 0;
1114 struct listnode *node;
1115
1116 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1117 ALOGV("%s:napb: not in true mode or non hdphones device",
1118 __func__);
1119 active = false;
1120 goto exit;
1121 }
1122
1123 list_for_each(node, &adev->usecase_list) {
1124 struct audio_usecase *uc;
1125 uc = node_to_item(node, struct audio_usecase, list);
1126 struct stream_out *curr_out =
1127 (struct stream_out*) uc->stream.out;
1128
1129 if (curr_out && PCM_PLAYBACK == uc->type) {
1130 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1131 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1132 uc->id, curr_out->sample_rate,
1133 curr_out->bit_width,
1134 platform_get_snd_device_name(uc->out_snd_device));
1135
1136 if (is_offload_usecase(uc->id) &&
1137 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1138 active = true;
1139 ALOGD("%s:napb:native stream detected", __func__);
1140 }
1141 }
1142 }
1143exit:
1144 return active;
1145}
1146
1147
1148static bool force_device_switch(struct audio_usecase *usecase)
1149{
1150 bool ret = false;
1151 bool is_it_true_mode = false;
1152
1153 if (is_offload_usecase(usecase->id) &&
1154 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001155 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1156 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1157 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301158 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1159 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1160 (!is_it_true_mode && adev->native_playback_enabled)){
1161 ret = true;
1162 ALOGD("napb: time to toggle native mode");
1163 }
1164 }
1165
1166 return ret;
1167}
1168
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001169int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001170{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001171 snd_device_t out_snd_device = SND_DEVICE_NONE;
1172 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 struct audio_usecase *usecase = NULL;
1174 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001175 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001176 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001177 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001179
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301180 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1181
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 usecase = get_usecase_from_list(adev, uc_id);
1183 if (usecase == NULL) {
1184 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1185 return -EINVAL;
1186 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001188 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001189 (usecase->type == VOIP_CALL) ||
1190 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001191 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001192 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001193 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 usecase->devices = usecase->stream.out->devices;
1195 } else {
1196 /*
1197 * If the voice call is active, use the sound devices of voice call usecase
1198 * so that it would not result any device switch. All the usecases will
1199 * be switched to new device when select_devices() is called for voice call
1200 * usecase. This is to avoid switching devices for voice call when
1201 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001202 * choose voice call device only if the use case device is
1203 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001204 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001205 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001206 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001207 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001208 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1209 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
1210 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 in_snd_device = vc_usecase->in_snd_device;
1212 out_snd_device = vc_usecase->out_snd_device;
1213 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001214 } else if (voice_extn_compress_voip_is_active(adev)) {
1215 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001216 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001217 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1218 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001219 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001220 in_snd_device = voip_usecase->in_snd_device;
1221 out_snd_device = voip_usecase->out_snd_device;
1222 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001223 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001224 hfp_ucid = audio_extn_hfp_get_usecase();
1225 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001226 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001227 in_snd_device = hfp_usecase->in_snd_device;
1228 out_snd_device = hfp_usecase->out_snd_device;
1229 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001230 }
1231 if (usecase->type == PCM_PLAYBACK) {
1232 usecase->devices = usecase->stream.out->devices;
1233 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001234 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001235 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001236 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001237 if (usecase->stream.out == adev->primary_output &&
1238 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001239 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001240 select_devices(adev, adev->active_input->usecase);
1241 }
1242 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243 } else if (usecase->type == PCM_CAPTURE) {
1244 usecase->devices = usecase->stream.in->device;
1245 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001246 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001247 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001248 if (adev->active_input &&
1249 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301250 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1251 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1252 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001253 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001254 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001255 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1256 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001257 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001258 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001259 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001260 }
1261 }
1262
1263 if (out_snd_device == usecase->out_snd_device &&
1264 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301265
1266 if (!force_device_switch(usecase))
1267 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268 }
1269
sangwoobc677242013-08-08 16:53:43 +09001270 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001271 out_snd_device, platform_get_snd_device_name(out_snd_device),
1272 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274 /*
1275 * Limitation: While in call, to do a device switch we need to disable
1276 * and enable both RX and TX devices though one of them is same as current
1277 * device.
1278 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001279 if ((usecase->type == VOICE_CALL) &&
1280 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1281 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001282 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001283 }
1284
1285 if (((usecase->type == VOICE_CALL) ||
1286 (usecase->type == VOIP_CALL)) &&
1287 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1288 /* Disable sidetone only if voice/voip call already exists */
1289 if (voice_is_call_state_active(adev) ||
1290 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001291 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001292 }
1293
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001294 /* Disable current sound devices */
1295 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001296 disable_audio_route(adev, usecase);
1297 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 }
1299
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001300 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001301 disable_audio_route(adev, usecase);
1302 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001303 }
1304
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001305 /* Applicable only on the targets that has external modem.
1306 * New device information should be sent to modem before enabling
1307 * the devices to reduce in-call device switch time.
1308 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001309 if ((usecase->type == VOICE_CALL) &&
1310 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1311 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001312 status = platform_switch_voice_call_enable_device_config(adev->platform,
1313 out_snd_device,
1314 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001315 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001316
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 /* Enable new sound devices */
1318 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001319 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001320 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001321 }
1322
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001323 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301324 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001325 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001326 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327
Avinash Vaish71a8b972014-07-24 15:36:33 +05301328 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001329 status = platform_switch_voice_call_device_post(adev->platform,
1330 out_snd_device,
1331 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301332 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001333 /* Enable sidetone only if voice/voip call already exists */
1334 if (voice_is_call_state_active(adev) ||
1335 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001336 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301337 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001338
sangwoo170731f2013-06-08 15:36:36 +09001339 usecase->in_snd_device = in_snd_device;
1340 usecase->out_snd_device = out_snd_device;
1341
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301342 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001343 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301344 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001345 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301346 usecase->stream.out->flags,
1347 usecase->stream.out->format,
1348 usecase->stream.out->sample_rate,
1349 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301350 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301351 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001352 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301353 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001354
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001355 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001356
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001357 /* Applicable only on the targets that has external modem.
1358 * Enable device command should be sent to modem only after
1359 * enabling voice call mixer controls
1360 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001361 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001362 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1363 out_snd_device,
1364 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301365 ALOGD("%s: done",__func__);
1366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 return status;
1368}
1369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370static int stop_input_stream(struct stream_in *in)
1371{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301372 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 struct audio_usecase *uc_info;
1374 struct audio_device *adev = in->dev;
1375
Eric Laurentc8400632013-02-14 19:04:54 -08001376 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001377
Eric Laurent994a6932013-07-17 11:51:42 -07001378 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001380 uc_info = get_usecase_from_list(adev, in->usecase);
1381 if (uc_info == NULL) {
1382 ALOGE("%s: Could not find the usecase (%d) in the list",
1383 __func__, in->usecase);
1384 return -EINVAL;
1385 }
1386
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001387 /* Close in-call recording streams */
1388 voice_check_and_stop_incall_rec_usecase(adev, in);
1389
Eric Laurent150dbfe2013-02-27 14:31:02 -08001390 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001391 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392
1393 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001394 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001395
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001396 list_remove(&uc_info->list);
1397 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001398
Eric Laurent994a6932013-07-17 11:51:42 -07001399 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 return ret;
1401}
1402
1403int start_input_stream(struct stream_in *in)
1404{
1405 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001406 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407 struct audio_usecase *uc_info;
1408 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301409 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001410
Mingming Yin2664a5b2015-09-03 10:53:11 -07001411 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1412 if (get_usecase_from_list(adev, usecase) == NULL)
1413 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301414 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1415 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001416
Naresh Tanniru80659832014-06-04 18:17:56 +05301417
1418 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301419 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301420 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301421 goto error_config;
1422 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301423
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001424 /* Check if source matches incall recording usecase criteria */
1425 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1426 if (ret)
1427 goto error_config;
1428 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001429 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1430
1431 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1432 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1433 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001434 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001435 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001436
Eric Laurentb23d5282013-05-14 15:27:20 -07001437 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 if (in->pcm_device_id < 0) {
1439 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1440 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001441 ret = -EINVAL;
1442 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444
1445 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001447
1448 if (!uc_info) {
1449 ret = -ENOMEM;
1450 goto error_config;
1451 }
1452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453 uc_info->id = in->usecase;
1454 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001455 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456 uc_info->devices = in->device;
1457 uc_info->in_snd_device = SND_DEVICE_NONE;
1458 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001460 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301461 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1462 adev->perf_lock_opts,
1463 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301466 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1467 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001468
1469 unsigned int flags = PCM_IN;
1470 unsigned int pcm_open_retry_count = 0;
1471
1472 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1473 flags |= PCM_MMAP | PCM_NOIRQ;
1474 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001475 } else if (in->realtime) {
1476 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001477 }
1478
1479 while (1) {
1480 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1481 flags, &in->config);
1482 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1483 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1484 if (in->pcm != NULL) {
1485 pcm_close(in->pcm);
1486 in->pcm = NULL;
1487 }
1488 if (pcm_open_retry_count-- == 0) {
1489 ret = -EIO;
1490 goto error_open;
1491 }
1492 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1493 continue;
1494 }
1495 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001497
1498 ALOGV("%s: pcm_prepare", __func__);
1499 ret = pcm_prepare(in->pcm);
1500 if (ret < 0) {
1501 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1502 pcm_close(in->pcm);
1503 in->pcm = NULL;
1504 goto error_open;
1505 }
1506
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001507 register_in_stream(in);
1508 if (in->realtime) {
1509 ret = pcm_start(in->pcm);
1510 if (ret < 0)
1511 goto error_open;
1512 }
1513
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301514 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001515 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001516
Eric Laurentc8400632013-02-14 19:04:54 -08001517 return ret;
1518
1519error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301520 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001522error_config:
1523 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301524 /*
1525 * sleep 50ms to allow sufficient time for kernel
1526 * drivers to recover incases like SSR.
1527 */
1528 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001530
1531 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532}
1533
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001534void lock_input_stream(struct stream_in *in)
1535{
1536 pthread_mutex_lock(&in->pre_lock);
1537 pthread_mutex_lock(&in->lock);
1538 pthread_mutex_unlock(&in->pre_lock);
1539}
1540
1541void lock_output_stream(struct stream_out *out)
1542{
1543 pthread_mutex_lock(&out->pre_lock);
1544 pthread_mutex_lock(&out->lock);
1545 pthread_mutex_unlock(&out->pre_lock);
1546}
1547
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001548/* must be called with out->lock locked */
1549static int send_offload_cmd_l(struct stream_out* out, int command)
1550{
1551 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1552
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001553 if (!cmd) {
1554 ALOGE("failed to allocate mem for command 0x%x", command);
1555 return -ENOMEM;
1556 }
1557
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001558 ALOGVV("%s %d", __func__, command);
1559
1560 cmd->cmd = command;
1561 list_add_tail(&out->offload_cmd_list, &cmd->node);
1562 pthread_cond_signal(&out->offload_cond);
1563 return 0;
1564}
1565
1566/* must be called iwth out->lock locked */
1567static void stop_compressed_output_l(struct stream_out *out)
1568{
1569 out->offload_state = OFFLOAD_STATE_IDLE;
1570 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001571 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001572 if (out->compr != NULL) {
1573 compress_stop(out->compr);
1574 while (out->offload_thread_blocked) {
1575 pthread_cond_wait(&out->cond, &out->lock);
1576 }
1577 }
1578}
1579
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001580bool is_offload_usecase(audio_usecase_t uc_id)
1581{
1582 unsigned int i;
1583 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1584 if (uc_id == offload_usecases[i])
1585 return true;
1586 }
1587 return false;
1588}
1589
vivek mehta446c3962015-09-14 10:57:35 -07001590static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001591{
vivek mehta446c3962015-09-14 10:57:35 -07001592 audio_usecase_t ret_uc = USECASE_INVALID;
1593 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001594 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001595 if (!adev->multi_offload_enable) {
1596 if (is_direct_pcm)
1597 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1598 else
1599 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001600
vivek mehta446c3962015-09-14 10:57:35 -07001601 pthread_mutex_lock(&adev->lock);
1602 if (get_usecase_from_list(adev, ret_uc) != NULL)
1603 ret_uc = USECASE_INVALID;
1604 pthread_mutex_unlock(&adev->lock);
1605
1606 return ret_uc;
1607 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001608
1609 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001610 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1611 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1612 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1613 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001614 break;
1615 }
1616 }
vivek mehta446c3962015-09-14 10:57:35 -07001617
1618 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1619 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001620}
1621
1622static void free_offload_usecase(struct audio_device *adev,
1623 audio_usecase_t uc_id)
1624{
vivek mehta446c3962015-09-14 10:57:35 -07001625 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001626 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001627
1628 if (!adev->multi_offload_enable)
1629 return;
1630
1631 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1632 if (offload_usecases[offload_uc_index] == uc_id) {
1633 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001634 break;
1635 }
1636 }
1637 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1638}
1639
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001640static void *offload_thread_loop(void *context)
1641{
1642 struct stream_out *out = (struct stream_out *) context;
1643 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001644 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001646 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1647 set_sched_policy(0, SP_FOREGROUND);
1648 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1649
1650 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001651 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001652 for (;;) {
1653 struct offload_cmd *cmd = NULL;
1654 stream_callback_event_t event;
1655 bool send_callback = false;
1656
1657 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1658 __func__, list_empty(&out->offload_cmd_list),
1659 out->offload_state);
1660 if (list_empty(&out->offload_cmd_list)) {
1661 ALOGV("%s SLEEPING", __func__);
1662 pthread_cond_wait(&out->offload_cond, &out->lock);
1663 ALOGV("%s RUNNING", __func__);
1664 continue;
1665 }
1666
1667 item = list_head(&out->offload_cmd_list);
1668 cmd = node_to_item(item, struct offload_cmd, node);
1669 list_remove(item);
1670
1671 ALOGVV("%s STATE %d CMD %d out->compr %p",
1672 __func__, out->offload_state, cmd->cmd, out->compr);
1673
1674 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1675 free(cmd);
1676 break;
1677 }
1678
1679 if (out->compr == NULL) {
1680 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001681 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001682 pthread_cond_signal(&out->cond);
1683 continue;
1684 }
1685 out->offload_thread_blocked = true;
1686 pthread_mutex_unlock(&out->lock);
1687 send_callback = false;
1688 switch(cmd->cmd) {
1689 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001690 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001691 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001692 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001693 send_callback = true;
1694 event = STREAM_CBK_EVENT_WRITE_READY;
1695 break;
1696 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001697 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301698 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001699 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301700 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001701 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301702 if (ret < 0)
1703 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301704 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301705 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001706 compress_drain(out->compr);
1707 else
1708 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301709 if (ret != -ENETRESET) {
1710 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301711 pthread_mutex_lock(&out->lock);
1712 out->send_new_metadata = 1;
1713 out->send_next_track_params = true;
1714 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301715 event = STREAM_CBK_EVENT_DRAIN_READY;
1716 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1717 } else
1718 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001719 break;
1720 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001721 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001723 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001724 send_callback = true;
1725 event = STREAM_CBK_EVENT_DRAIN_READY;
1726 break;
1727 default:
1728 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1729 break;
1730 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001731 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001732 out->offload_thread_blocked = false;
1733 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001734 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001735 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001736 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001737 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001738 free(cmd);
1739 }
1740
1741 pthread_cond_signal(&out->cond);
1742 while (!list_empty(&out->offload_cmd_list)) {
1743 item = list_head(&out->offload_cmd_list);
1744 list_remove(item);
1745 free(node_to_item(item, struct offload_cmd, node));
1746 }
1747 pthread_mutex_unlock(&out->lock);
1748
1749 return NULL;
1750}
1751
1752static int create_offload_callback_thread(struct stream_out *out)
1753{
1754 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1755 list_init(&out->offload_cmd_list);
1756 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1757 offload_thread_loop, out);
1758 return 0;
1759}
1760
1761static int destroy_offload_callback_thread(struct stream_out *out)
1762{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001763 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 stop_compressed_output_l(out);
1765 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1766
1767 pthread_mutex_unlock(&out->lock);
1768 pthread_join(out->offload_thread, (void **) NULL);
1769 pthread_cond_destroy(&out->offload_cond);
1770
1771 return 0;
1772}
1773
Mingming Yin21854652016-04-13 11:54:02 -07001774static bool allow_hdmi_channel_config(struct audio_device *adev,
1775 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001776{
1777 struct listnode *node;
1778 struct audio_usecase *usecase;
1779 bool ret = true;
1780
Mingming Yin21854652016-04-13 11:54:02 -07001781 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1782 ret = false;
1783 goto exit;
1784 }
1785
1786 if (audio_extn_passthru_is_active()) {
1787 ALOGI("%s: Compress audio passthrough is active,"
1788 "no HDMI config change allowed", __func__);
1789 ret = false;
1790 goto exit;
1791 }
1792
Eric Laurent07eeafd2013-10-06 12:52:49 -07001793 list_for_each(node, &adev->usecase_list) {
1794 usecase = node_to_item(node, struct audio_usecase, list);
1795 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1796 /*
1797 * If voice call is already existing, do not proceed further to avoid
1798 * disabling/enabling both RX and TX devices, CSD calls, etc.
1799 * Once the voice call done, the HDMI channels can be configured to
1800 * max channels of remaining use cases.
1801 */
1802 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001803 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001804 __func__);
1805 ret = false;
1806 break;
1807 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001808 if (!enable_passthru) {
1809 ALOGV("%s: multi channel playback is active, "
1810 "no change in HDMI channels", __func__);
1811 ret = false;
1812 break;
1813 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001814 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001815 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001816 if (!enable_passthru) {
1817 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1818 ", no change in HDMI channels", __func__,
1819 usecase->stream.out->channel_mask);
1820 ret = false;
1821 break;
1822 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001823 }
1824 }
1825 }
Mingming Yin21854652016-04-13 11:54:02 -07001826 ALOGV("allow hdmi config %d", ret);
1827exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001828 return ret;
1829}
1830
Mingming Yin21854652016-04-13 11:54:02 -07001831static int check_and_set_hdmi_config(struct audio_device *adev,
1832 uint32_t channels,
1833 uint32_t sample_rate,
1834 audio_format_t format,
1835 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001836{
1837 struct listnode *node;
1838 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001839 int32_t factor = 1;
1840 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001841
Mingming Yin21854652016-04-13 11:54:02 -07001842 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1843 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001844
Mingming Yin21854652016-04-13 11:54:02 -07001845 if (channels != adev->cur_hdmi_channels) {
1846 ALOGV("channel does not match current hdmi channels");
1847 config = true;
1848 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001849
Mingming Yin21854652016-04-13 11:54:02 -07001850 if (sample_rate != adev->cur_hdmi_sample_rate) {
1851 ALOGV("sample rate does not match current hdmi sample rate");
1852 config = true;
1853 }
1854
1855 if (format != adev->cur_hdmi_format) {
1856 ALOGV("format does not match current hdmi format");
1857 config = true;
1858 }
1859
1860 /* TBD - add check for bit width */
1861 if (!config) {
1862 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001863 return 0;
1864 }
1865
Mingming Yin21854652016-04-13 11:54:02 -07001866 if (enable_passthru &&
1867 (format == AUDIO_FORMAT_E_AC3)) {
1868 ALOGV("factor 4 for E_AC3 passthru");
1869 factor = 4;
1870 }
1871
1872 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1873 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001874 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001875 adev->cur_hdmi_format = format;
1876 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001877
1878 /*
1879 * Deroute all the playback streams routed to HDMI so that
1880 * the back end is deactivated. Note that backend will not
1881 * be deactivated if any one stream is connected to it.
1882 */
1883 list_for_each(node, &adev->usecase_list) {
1884 usecase = node_to_item(node, struct audio_usecase, list);
1885 if (usecase->type == PCM_PLAYBACK &&
1886 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001887 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001888 }
1889 }
1890
Mingming Yin21854652016-04-13 11:54:02 -07001891 bool was_active = audio_extn_keep_alive_is_active();
1892 if (was_active)
1893 audio_extn_keep_alive_stop();
1894
Eric Laurent07eeafd2013-10-06 12:52:49 -07001895 /*
1896 * Enable all the streams disabled above. Now the HDMI backend
1897 * will be activated with new channel configuration
1898 */
1899 list_for_each(node, &adev->usecase_list) {
1900 usecase = node_to_item(node, struct audio_usecase, list);
1901 if (usecase->type == PCM_PLAYBACK &&
1902 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001903 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001904 }
1905 }
1906
Mingming Yin21854652016-04-13 11:54:02 -07001907 if (was_active)
1908 audio_extn_keep_alive_start();
1909
Eric Laurent07eeafd2013-10-06 12:52:49 -07001910 return 0;
1911}
1912
Mingming Yin21854652016-04-13 11:54:02 -07001913/* called with out lock taken */
1914static int check_and_set_hdmi_backend(struct stream_out *out)
1915{
1916 struct audio_device *adev = out->dev;
1917 int ret;
1918 bool enable_passthru = false;
1919
1920 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1921 return -1;
1922
1923 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1924
1925 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301926 audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07001927 enable_passthru = true;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301928 ALOGV("%s : enable_passthru is set to true", __func__);
Mingming Yin21854652016-04-13 11:54:02 -07001929 }
1930
1931 /* Check if change in HDMI channel config is allowed */
1932 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1933 return -EPERM;
1934 }
1935
1936 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1937 uint32_t channels;
1938 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1939
1940 if (enable_passthru) {
1941 audio_extn_passthru_on_start(out);
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301942 audio_extn_passthru_update_stream_configuration(adev, out);
Mingming Yin21854652016-04-13 11:54:02 -07001943 }
1944
1945 /* For pass through case, the backend should be configured as stereo */
1946 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1947 out->compr_config.codec->ch_in;
1948
1949 ret = check_and_set_hdmi_config(adev, channels,
1950 out->sample_rate, out->format,
1951 enable_passthru);
1952 } else
1953 ret = check_and_set_hdmi_config(adev, out->config.channels,
1954 out->config.rate,
1955 out->format,
1956 false);
1957 return ret;
1958}
1959
1960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961static int stop_output_stream(struct stream_out *out)
1962{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301963 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 struct audio_usecase *uc_info;
1965 struct audio_device *adev = out->dev;
1966
Eric Laurent994a6932013-07-17 11:51:42 -07001967 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001968 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 uc_info = get_usecase_from_list(adev, out->usecase);
1970 if (uc_info == NULL) {
1971 ALOGE("%s: Could not find the usecase (%d) in the list",
1972 __func__, out->usecase);
1973 return -EINVAL;
1974 }
1975
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001976 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301977 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001978 if (adev->visualizer_stop_output != NULL)
1979 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001980
1981 audio_extn_dts_remove_state_notifier_node(out->usecase);
1982
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001983 if (adev->offload_effects_stop_output != NULL)
1984 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1985 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001986
Eric Laurent150dbfe2013-02-27 14:31:02 -08001987 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001988 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001989
1990 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001991 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001993 list_remove(&uc_info->list);
1994 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001996 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301997 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001998 ALOGV("Disable passthrough , reset mixer to pcm");
1999 /* NO_PASSTHROUGH */
2000 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002001
Mingming Yin21854652016-04-13 11:54:02 -07002002 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002003 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2004 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002005
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302006 /* Must be called after removing the usecase from list */
2007 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2008 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
2009 DEFAULT_HDMI_OUT_SAMPLE_RATE,
2010 DEFAULT_HDMI_OUT_FORMAT,
2011 false);
Eric Laurent994a6932013-07-17 11:51:42 -07002012 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013 return ret;
2014}
2015
2016int start_output_stream(struct stream_out *out)
2017{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 struct audio_usecase *uc_info;
2020 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302021 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002023 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2024 ret = -EINVAL;
2025 goto error_config;
2026 }
2027
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302028 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2029 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2030 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302031
Naresh Tanniru80659832014-06-04 18:17:56 +05302032 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302033 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302034 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302035 goto error_config;
2036 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302037
Eric Laurentb23d5282013-05-14 15:27:20 -07002038 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039 if (out->pcm_device_id < 0) {
2040 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2041 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002042 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002043 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 }
2045
2046 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002047
2048 if (!uc_info) {
2049 ret = -ENOMEM;
2050 goto error_config;
2051 }
2052
Mingming Yin21854652016-04-13 11:54:02 -07002053 /* This must be called before adding this usecase to the list */
2054 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2055 /* This call can fail if compress pass thru is already active */
2056 check_and_set_hdmi_backend(out);
2057 }
2058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 uc_info->id = out->usecase;
2060 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002061 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002062 uc_info->devices = out->devices;
2063 uc_info->in_snd_device = SND_DEVICE_NONE;
2064 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002065 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302067 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2068 adev->perf_lock_opts,
2069 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002070 select_devices(adev, out->usecase);
2071
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002072 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2073 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002074 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002075 unsigned int flags = PCM_OUT;
2076 unsigned int pcm_open_retry_count = 0;
2077 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2078 flags |= PCM_MMAP | PCM_NOIRQ;
2079 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002080 } else if (out->realtime) {
2081 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002082 } else
2083 flags |= PCM_MONOTONIC;
2084
2085 while (1) {
2086 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2087 flags, &out->config);
2088 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2089 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2090 if (out->pcm != NULL) {
2091 pcm_close(out->pcm);
2092 out->pcm = NULL;
2093 }
2094 if (pcm_open_retry_count-- == 0) {
2095 ret = -EIO;
2096 goto error_open;
2097 }
2098 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2099 continue;
2100 }
2101 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002103
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002104 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2105 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002106
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002107 ALOGV("%s: pcm_prepare", __func__);
2108 if (pcm_is_ready(out->pcm)) {
2109 ret = pcm_prepare(out->pcm);
2110 if (ret < 0) {
2111 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2112 pcm_close(out->pcm);
2113 out->pcm = NULL;
2114 goto error_open;
2115 }
2116 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002118 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2119 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002121 out->compr = compress_open(adev->snd_card,
2122 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002123 COMPRESS_IN, &out->compr_config);
2124 if (out->compr && !is_compress_ready(out->compr)) {
2125 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2126 compress_close(out->compr);
2127 out->compr = NULL;
2128 ret = -EIO;
2129 goto error_open;
2130 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302131 /* compress_open sends params of the track, so reset the flag here */
2132 out->is_compr_metadata_avail = false;
2133
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 if (out->offload_callback)
2135 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002136
Fred Oh3f43e742015-03-04 18:42:34 -08002137 /* Since small bufs uses blocking writes, a write will be blocked
2138 for the default max poll time (20s) in the event of an SSR.
2139 Reduce the poll time to observe and deal with SSR faster.
2140 */
Ashish Jain5106d362016-05-11 19:23:33 +05302141 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002142 compress_set_max_poll_wait(out->compr, 1000);
2143 }
2144
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002145 audio_extn_dts_create_state_notifier_node(out->usecase);
2146 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2147 popcount(out->channel_mask),
2148 out->playback_started);
2149
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002150#ifdef DS1_DOLBY_DDP_ENABLED
2151 if (audio_extn_is_dolby_format(out->format))
2152 audio_extn_dolby_send_ddp_endp_params(adev);
2153#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302154 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002155 if (adev->visualizer_start_output != NULL)
2156 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2157 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302158 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002159 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002160 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002162
2163 if (ret == 0) {
2164 register_out_stream(out);
2165 if (out->realtime) {
2166 ret = pcm_start(out->pcm);
2167 if (ret < 0)
2168 goto error_open;
2169 }
2170 }
2171
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302172 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002173 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002174
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002175 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002176error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302177 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002179error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302180 /*
2181 * sleep 50ms to allow sufficient time for kernel
2182 * drivers to recover incases like SSR.
2183 */
2184 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002185 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186}
2187
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188static int check_input_parameters(uint32_t sample_rate,
2189 audio_format_t format,
2190 int channel_count)
2191{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002192 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302194 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2195 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2196 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002197 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302198 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002199
2200 switch (channel_count) {
2201 case 1:
2202 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302203 case 3:
2204 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002205 case 6:
2206 break;
2207 default:
2208 ret = -EINVAL;
2209 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210
2211 switch (sample_rate) {
2212 case 8000:
2213 case 11025:
2214 case 12000:
2215 case 16000:
2216 case 22050:
2217 case 24000:
2218 case 32000:
2219 case 44100:
2220 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302221 case 96000:
2222 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 break;
2224 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002225 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 }
2227
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002228 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229}
2230
2231static size_t get_input_buffer_size(uint32_t sample_rate,
2232 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002233 int channel_count,
2234 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235{
2236 size_t size = 0;
2237
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002238 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2239 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002241 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002242 if (is_low_latency)
2243 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302244
2245 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002247 /* make sure the size is multiple of 32 bytes
2248 * At 48 kHz mono 16-bit PCM:
2249 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2250 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2251 */
2252 size += 0x1f;
2253 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002254
2255 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256}
2257
Ashish Jain5106d362016-05-11 19:23:33 +05302258static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2259{
2260 uint64_t actual_frames_rendered = 0;
2261 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2262
2263 /* This adjustment accounts for buffering after app processor.
2264 * It is based on estimated DSP latency per use case, rather than exact.
2265 */
2266 int64_t platform_latency = platform_render_latency(out->usecase) *
2267 out->sample_rate / 1000000LL;
2268
2269 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2270 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2271 * hence only estimate.
2272 */
2273 int64_t signed_frames = out->written - kernel_buffer_size;
2274
2275 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2276
2277 if (signed_frames > 0)
2278 actual_frames_rendered = signed_frames;
2279
2280 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2281 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2282 (long long int)out->written, (int)kernel_buffer_size,
2283 audio_bytes_per_sample(out->compr_config.codec->format),
2284 popcount(out->channel_mask));
2285
2286 return actual_frames_rendered;
2287}
2288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002289static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2290{
2291 struct stream_out *out = (struct stream_out *)stream;
2292
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002293 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294}
2295
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002296static int out_set_sample_rate(struct audio_stream *stream __unused,
2297 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298{
2299 return -ENOSYS;
2300}
2301
2302static size_t out_get_buffer_size(const struct audio_stream *stream)
2303{
2304 struct stream_out *out = (struct stream_out *)stream;
2305
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002306 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002307 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002308 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2309 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302310 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302311 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002312
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002313 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002314 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002315}
2316
2317static uint32_t out_get_channels(const struct audio_stream *stream)
2318{
2319 struct stream_out *out = (struct stream_out *)stream;
2320
2321 return out->channel_mask;
2322}
2323
2324static audio_format_t out_get_format(const struct audio_stream *stream)
2325{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002326 struct stream_out *out = (struct stream_out *)stream;
2327
2328 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329}
2330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002331static int out_set_format(struct audio_stream *stream __unused,
2332 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
2334 return -ENOSYS;
2335}
2336
2337static int out_standby(struct audio_stream *stream)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302342 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2343 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002345 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002347 if (adev->adm_deregister_stream)
2348 adev->adm_deregister_stream(adev->adm_data, out->handle);
2349
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002350 if (is_offload_usecase(out->usecase))
2351 stop_compressed_output_l(out);
2352
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002353 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002355 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2356 voice_extn_compress_voip_close_output_stream(stream);
2357 pthread_mutex_unlock(&adev->lock);
2358 pthread_mutex_unlock(&out->lock);
2359 ALOGD("VOIP output entered standby");
2360 return 0;
2361 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002362 if (out->pcm) {
2363 pcm_close(out->pcm);
2364 out->pcm = NULL;
2365 }
2366 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002367 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302368 out->send_next_track_params = false;
2369 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002370 out->gapless_mdata.encoder_delay = 0;
2371 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372 if (out->compr != NULL) {
2373 compress_close(out->compr);
2374 out->compr = NULL;
2375 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002376 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002378 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 }
2380 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302381 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 return 0;
2383}
2384
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002385static int out_dump(const struct audio_stream *stream __unused,
2386 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002387{
2388 return 0;
2389}
2390
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002391static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2392{
2393 int ret = 0;
2394 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002395
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002396 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002397 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002398 return -EINVAL;
2399 }
2400
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302401 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002402
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002403 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2404 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302405 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002406 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002407 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2408 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302409 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002410 }
2411
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002412 ALOGV("%s new encoder delay %u and padding %u", __func__,
2413 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2414
2415 return 0;
2416}
2417
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002418static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2419{
2420 return out == adev->primary_output || out == adev->voice_tx_output;
2421}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2424{
2425 struct stream_out *out = (struct stream_out *)stream;
2426 struct audio_device *adev = out->dev;
2427 struct str_parms *parms;
2428 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002429 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
sangwoobc677242013-08-08 16:53:43 +09002431 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002432 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302434 if (!parms)
2435 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002436 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2437 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002439 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002440 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002442 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002443 * When HDMI cable is unplugged the music playback is paused and
2444 * the policy manager sends routing=0. But the audioflinger continues
2445 * to write data until standby time (3sec). As the HDMI core is
2446 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002447 * Avoid this by routing audio to speaker until standby.
2448 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002449 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2450 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302451 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002452 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2453 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002454 }
2455
2456 /*
2457 * select_devices() call below switches all the usecases on the same
2458 * backend to the new device. Refer to check_usecases_codec_backend() in
2459 * the select_devices(). But how do we undo this?
2460 *
2461 * For example, music playback is active on headset (deep-buffer usecase)
2462 * and if we go to ringtones and select a ringtone, low-latency usecase
2463 * will be started on headset+speaker. As we can't enable headset+speaker
2464 * and headset devices at the same time, select_devices() switches the music
2465 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2466 * So when the ringtone playback is completed, how do we undo the same?
2467 *
2468 * We are relying on the out_set_parameters() call on deep-buffer output,
2469 * once the ringtone playback is ended.
2470 * NOTE: We should not check if the current devices are same as new devices.
2471 * Because select_devices() must be called to switch back the music
2472 * playback to headset.
2473 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002474 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002475 audio_devices_t new_dev = val;
2476 bool same_dev = out->devices == new_dev;
2477 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002478
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002479 if (output_drives_call(adev, out)) {
2480 if(!voice_is_in_call(adev)) {
2481 if (adev->mode == AUDIO_MODE_IN_CALL) {
2482 adev->current_call_output = out;
2483 ret = voice_start_call(adev);
2484 }
2485 } else {
2486 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002487 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002488 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002489 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002490
2491 if (!out->standby) {
2492 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2493 adev->perf_lock_opts,
2494 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002495 if (!same_dev) {
2496 ALOGV("update routing change");
2497 out->routing_change = true;
2498 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002499 select_devices(adev, out->usecase);
2500 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2501 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002502 }
2503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002505 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002507
2508 if (out == adev->primary_output) {
2509 pthread_mutex_lock(&adev->lock);
2510 audio_extn_set_parameters(adev, parms);
2511 pthread_mutex_unlock(&adev->lock);
2512 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002513 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002514 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002515 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002516
2517 audio_extn_dts_create_state_notifier_node(out->usecase);
2518 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2519 popcount(out->channel_mask),
2520 out->playback_started);
2521
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002522 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002523 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302526error:
Eric Laurent994a6932013-07-17 11:51:42 -07002527 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 return ret;
2529}
2530
2531static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2532{
2533 struct stream_out *out = (struct stream_out *)stream;
2534 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002535 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 char value[256];
2537 struct str_parms *reply = str_parms_create();
2538 size_t i, j;
2539 int ret;
2540 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002541
2542 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002543 if (reply) {
2544 str_parms_destroy(reply);
2545 }
2546 if (query) {
2547 str_parms_destroy(query);
2548 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002549 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2550 return NULL;
2551 }
2552
Eric Laurent994a6932013-07-17 11:51:42 -07002553 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2555 if (ret >= 0) {
2556 value[0] = '\0';
2557 i = 0;
2558 while (out->supported_channel_masks[i] != 0) {
2559 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2560 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2561 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002562 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002564 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 first = false;
2566 break;
2567 }
2568 }
2569 i++;
2570 }
2571 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2572 str = str_parms_to_str(reply);
2573 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002574 voice_extn_out_get_parameters(out, query, reply);
2575 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002576 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002577 free(str);
2578 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002579 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002581
Alexy Joseph62142aa2015-11-16 15:10:34 -08002582
2583 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2584 if (ret >= 0) {
2585 value[0] = '\0';
2586 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2587 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302588 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002589 } else {
2590 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302591 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002592 }
2593 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002594 if (str)
2595 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002596 str = str_parms_to_str(reply);
2597 }
2598
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002599 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2600 if (ret >= 0) {
2601 value[0] = '\0';
2602 i = 0;
2603 first = true;
2604 while (out->supported_formats[i] != 0) {
2605 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2606 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2607 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002608 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002609 }
2610 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2611 first = false;
2612 break;
2613 }
2614 }
2615 i++;
2616 }
2617 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002618 if (str)
2619 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002620 str = str_parms_to_str(reply);
2621 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002622
2623 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2624 if (ret >= 0) {
2625 value[0] = '\0';
2626 i = 0;
2627 first = true;
2628 while (out->supported_sample_rates[i] != 0) {
2629 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2630 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2631 if (!first) {
2632 strlcat(value, "|", sizeof(value));
2633 }
2634 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2635 first = false;
2636 break;
2637 }
2638 }
2639 i++;
2640 }
2641 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2642 if (str)
2643 free(str);
2644 str = str_parms_to_str(reply);
2645 }
2646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 str_parms_destroy(query);
2648 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002649 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 return str;
2651}
2652
2653static uint32_t out_get_latency(const struct audio_stream_out *stream)
2654{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002655 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002657 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658
Alexy Josephaa54c872014-12-03 02:46:47 -08002659 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002660 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002661 } else if (out->realtime) {
2662 // since the buffer won't be filled up faster than realtime,
2663 // return a smaller number
2664 if (out->config.rate)
2665 period_ms = (out->af_period_multiplier * out->config.period_size *
2666 1000) / (out->config.rate);
2667 else
2668 period_ms = 0;
2669 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002670 } else {
2671 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002672 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002673 }
2674
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302675 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002676 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677}
2678
2679static int out_set_volume(struct audio_stream_out *stream, float left,
2680 float right)
2681{
Eric Laurenta9024de2013-04-04 09:19:12 -07002682 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 int volume[2];
2684
Eric Laurenta9024de2013-04-04 09:19:12 -07002685 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2686 /* only take left channel into account: the API is for stereo anyway */
2687 out->muted = (left == 0.0f);
2688 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002689 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302690 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002691 /*
2692 * Set mute or umute on HDMI passthrough stream.
2693 * Only take left channel into account.
2694 * Mute is 0 and unmute 1
2695 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302696 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002697 } else {
2698 char mixer_ctl_name[128];
2699 struct audio_device *adev = out->dev;
2700 struct mixer_ctl *ctl;
2701 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002702 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002703
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002704 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2705 "Compress Playback %d Volume", pcm_device_id);
2706 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2707 if (!ctl) {
2708 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2709 __func__, mixer_ctl_name);
2710 return -EINVAL;
2711 }
2712 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2713 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2714 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2715 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002716 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002717 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 return -ENOSYS;
2720}
2721
2722static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2723 size_t bytes)
2724{
2725 struct stream_out *out = (struct stream_out *)stream;
2726 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302727 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002728 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002730 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302731
Naresh Tanniru80659832014-06-04 18:17:56 +05302732 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002733
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302734 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302735 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302736 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2737 pthread_mutex_unlock(&out->lock);
2738 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302739 } else {
2740 /* increase written size during SSR to avoid mismatch
2741 * with the written frames count in AF
2742 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302743 if (audio_bytes_per_sample(out->format) != 0)
2744 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302745 ALOGD(" %s: sound card is not active/SSR state", __func__);
2746 ret= -EIO;
2747 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302748 }
2749 }
2750
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302751 if (audio_extn_passthru_should_drop_data(out)) {
2752 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2753 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2754 out_get_sample_rate(&out->stream.common));
2755 goto exit;
2756 }
2757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002759 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002760 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002761 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2762 ret = voice_extn_compress_voip_start_output_stream(out);
2763 else
2764 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002765 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002766 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002768 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769 goto exit;
2770 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002771
2772 if (last_known_cal_step != -1) {
2773 ALOGD("%s: retry previous failed cal level set", __func__);
2774 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2775 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777
Ashish Jain81eb2a82015-05-13 10:52:34 +05302778 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002779 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302780 adev->is_channel_status_set = true;
2781 }
2782
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002783 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002784 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002785 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002786 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002787 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2788 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302789 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2790 ALOGD("copl(%p):send next track params in gapless", out);
2791 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2792 out->send_next_track_params = false;
2793 out->is_compr_metadata_avail = false;
2794 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002795 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302796 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302797 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002798
Ashish Jain83a6cc22016-06-28 14:34:17 +05302799 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302800 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302801 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302802 pthread_mutex_unlock(&out->lock);
2803 return -EINVAL;
2804 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302805 audio_format_t dst_format = out->hal_op_format;
2806 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302807
2808 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2809 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2810
Ashish Jain83a6cc22016-06-28 14:34:17 +05302811 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302812 dst_format,
2813 buffer,
2814 src_format,
2815 frames);
2816
Ashish Jain83a6cc22016-06-28 14:34:17 +05302817 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302818 bytes_to_write);
2819
2820 /*Convert written bytes in audio flinger format*/
2821 if (ret > 0)
2822 ret = ((ret * format_to_bitwidth_table[out->format]) /
2823 format_to_bitwidth_table[dst_format]);
2824 }
2825 } else
2826 ret = compress_write(out->compr, buffer, bytes);
2827
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302828 if (ret < 0)
2829 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302830 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002831 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302832 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302834 } else if (-ENETRESET == ret) {
2835 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2836 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2837 pthread_mutex_unlock(&out->lock);
2838 out_standby(&out->stream.common);
2839 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002840 }
Ashish Jain5106d362016-05-11 19:23:33 +05302841 if ( ret == (ssize_t)bytes && !out->non_blocking)
2842 out->written += bytes;
2843
Naresh Tanniru80659832014-06-04 18:17:56 +05302844 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002846 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 out->playback_started = 1;
2848 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002849
2850 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2851 popcount(out->channel_mask),
2852 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853 }
2854 pthread_mutex_unlock(&out->lock);
2855 return ret;
2856 } else {
2857 if (out->pcm) {
2858 if (out->muted)
2859 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002860
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302861 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002862
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002863 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002864
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002865 if (out->config.rate)
2866 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2867 out->config.rate;
2868
2869 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2870
2871 request_out_focus(out, ns);
2872
2873 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002874 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002875 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302876 out->convert_buffer != NULL) {
2877
2878 memcpy_by_audio_format(out->convert_buffer,
2879 out->hal_op_format,
2880 buffer,
2881 out->hal_ip_format,
2882 out->config.period_size * out->config.channels);
2883
2884 ret = pcm_write(out->pcm, out->convert_buffer,
2885 (out->config.period_size *
2886 out->config.channels *
2887 format_to_bitwidth_table[out->hal_op_format]));
2888 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002889 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302890 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002891
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002892 release_out_focus(out);
2893
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302894 if (ret < 0)
2895 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302896 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2897 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2898 else
2899 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002900 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 }
2902
2903exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302904 /* ToDo: There may be a corner case when SSR happens back to back during
2905 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302906 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302907 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302908 }
2909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910 pthread_mutex_unlock(&out->lock);
2911
2912 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002913 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002914 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302915 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302916 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302917 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302918 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302919 out->standby = true;
2920 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302922 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302923 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 }
2925 return bytes;
2926}
2927
2928static int out_get_render_position(const struct audio_stream_out *stream,
2929 uint32_t *dsp_frames)
2930{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002931 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302932 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002933
2934 if (dsp_frames == NULL)
2935 return -EINVAL;
2936
2937 *dsp_frames = 0;
2938 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002939 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302940
2941 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2942 * this operation and adev_close_output_stream(where out gets reset).
2943 */
2944 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2945 *dsp_frames = get_actual_pcm_frames_rendered(out);
2946 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2947 return 0;
2948 }
2949
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002950 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302951 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302952 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302954 if (ret < 0)
2955 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302957 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002958 }
2959 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302960 if (-ENETRESET == ret) {
2961 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2962 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2963 return -EINVAL;
2964 } else if(ret < 0) {
2965 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2966 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302967 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2968 /*
2969 * Handle corner case where compress session is closed during SSR
2970 * and timestamp is queried
2971 */
2972 ALOGE(" ERROR: sound card not active, return error");
2973 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302974 } else {
2975 return 0;
2976 }
Zhou Song32a556e2015-05-05 10:46:56 +08002977 } else if (audio_is_linear_pcm(out->format)) {
2978 *dsp_frames = out->written;
2979 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002980 } else
2981 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982}
2983
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002984static int out_add_audio_effect(const struct audio_stream *stream __unused,
2985 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986{
2987 return 0;
2988}
2989
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002990static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2991 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992{
2993 return 0;
2994}
2995
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002996static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2997 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998{
2999 return -EINVAL;
3000}
3001
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003002static int out_get_presentation_position(const struct audio_stream_out *stream,
3003 uint64_t *frames, struct timespec *timestamp)
3004{
3005 struct stream_out *out = (struct stream_out *)stream;
3006 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003007 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003008
Ashish Jain5106d362016-05-11 19:23:33 +05303009 /* below piece of code is not guarded against any lock because audioFliner serializes
3010 * this operation and adev_close_output_stream( where out gets reset).
3011 */
3012 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3013 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3014 *frames = get_actual_pcm_frames_rendered(out);
3015 /* this is the best we can do */
3016 clock_gettime(CLOCK_MONOTONIC, timestamp);
3017 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3018 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3019 return 0;
3020 }
3021
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003022 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003023
Ashish Jain5106d362016-05-11 19:23:33 +05303024 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3025 ret = compress_get_tstamp(out->compr, &dsp_frames,
3026 &out->sample_rate);
3027 ALOGVV("%s rendered frames %ld sample_rate %d",
3028 __func__, dsp_frames, out->sample_rate);
3029 *frames = dsp_frames;
3030 if (ret < 0)
3031 ret = -errno;
3032 if (-ENETRESET == ret) {
3033 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3034 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3035 ret = -EINVAL;
3036 } else
3037 ret = 0;
3038 /* this is the best we can do */
3039 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003040 } else {
3041 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003042 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003043 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3044 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003045 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003046 // This adjustment accounts for buffering after app processor.
3047 // It is based on estimated DSP latency per use case, rather than exact.
3048 signed_frames -=
3049 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3050
Eric Laurent949a0892013-09-20 09:20:13 -07003051 // It would be unusual for this value to be negative, but check just in case ...
3052 if (signed_frames >= 0) {
3053 *frames = signed_frames;
3054 ret = 0;
3055 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003056 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303057 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3058 *frames = out->written;
3059 clock_gettime(CLOCK_MONOTONIC, timestamp);
3060 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003061 }
3062 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003063 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003064 return ret;
3065}
3066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067static int out_set_callback(struct audio_stream_out *stream,
3068 stream_callback_t callback, void *cookie)
3069{
3070 struct stream_out *out = (struct stream_out *)stream;
3071
3072 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003073 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003074 out->offload_callback = callback;
3075 out->offload_cookie = cookie;
3076 pthread_mutex_unlock(&out->lock);
3077 return 0;
3078}
3079
3080static int out_pause(struct audio_stream_out* stream)
3081{
3082 struct stream_out *out = (struct stream_out *)stream;
3083 int status = -ENOSYS;
3084 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003085 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003086 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003087 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303089 struct audio_device *adev = out->dev;
3090 int snd_scard_state = get_snd_card_state(adev);
3091
3092 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3093 status = compress_pause(out->compr);
3094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003096
Mingming Yin21854652016-04-13 11:54:02 -07003097 if (audio_extn_passthru_is_active()) {
3098 ALOGV("offload use case, pause passthru");
3099 audio_extn_passthru_on_pause(out);
3100 }
3101
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303102 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003103 audio_extn_dts_notify_playback_state(out->usecase, 0,
3104 out->sample_rate, popcount(out->channel_mask),
3105 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 }
3107 pthread_mutex_unlock(&out->lock);
3108 }
3109 return status;
3110}
3111
3112static int out_resume(struct audio_stream_out* stream)
3113{
3114 struct stream_out *out = (struct stream_out *)stream;
3115 int status = -ENOSYS;
3116 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003117 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003118 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003120 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303122 struct audio_device *adev = out->dev;
3123 int snd_scard_state = get_snd_card_state(adev);
3124
Mingming Yin21854652016-04-13 11:54:02 -07003125 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3126 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3127 pthread_mutex_lock(&out->dev->lock);
3128 ALOGV("offload resume, check and set hdmi backend again");
3129 check_and_set_hdmi_backend(out);
3130 pthread_mutex_unlock(&out->dev->lock);
3131 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303132 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003133 }
3134 if (!status) {
3135 out->offload_state = OFFLOAD_STATE_PLAYING;
3136 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303137 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003138 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3139 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 }
3141 pthread_mutex_unlock(&out->lock);
3142 }
3143 return status;
3144}
3145
3146static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3147{
3148 struct stream_out *out = (struct stream_out *)stream;
3149 int status = -ENOSYS;
3150 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003151 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003152 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003153 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3154 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3155 else
3156 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3157 pthread_mutex_unlock(&out->lock);
3158 }
3159 return status;
3160}
3161
3162static int out_flush(struct audio_stream_out* stream)
3163{
3164 struct stream_out *out = (struct stream_out *)stream;
3165 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003166 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003167 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003168 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303170 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003171 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003172 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003173 return 0;
3174 }
3175 return -ENOSYS;
3176}
3177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178/** audio_stream_in implementation **/
3179static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3180{
3181 struct stream_in *in = (struct stream_in *)stream;
3182
3183 return in->config.rate;
3184}
3185
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003186static int in_set_sample_rate(struct audio_stream *stream __unused,
3187 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003188{
3189 return -ENOSYS;
3190}
3191
3192static size_t in_get_buffer_size(const struct audio_stream *stream)
3193{
3194 struct stream_in *in = (struct stream_in *)stream;
3195
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003196 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3197 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003198 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3199 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003200
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003201 return in->config.period_size * in->af_period_multiplier *
3202 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203}
3204
3205static uint32_t in_get_channels(const struct audio_stream *stream)
3206{
3207 struct stream_in *in = (struct stream_in *)stream;
3208
3209 return in->channel_mask;
3210}
3211
3212static audio_format_t in_get_format(const struct audio_stream *stream)
3213{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003214 struct stream_in *in = (struct stream_in *)stream;
3215
3216 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217}
3218
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003219static int in_set_format(struct audio_stream *stream __unused,
3220 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221{
3222 return -ENOSYS;
3223}
3224
3225static int in_standby(struct audio_stream *stream)
3226{
3227 struct stream_in *in = (struct stream_in *)stream;
3228 struct audio_device *adev = in->dev;
3229 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303230 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3231 stream, in->usecase, use_case_table[in->usecase]);
3232
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003233 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003234 if (!in->standby && in->is_st_session) {
3235 ALOGD("%s: sound trigger pcm stop lab", __func__);
3236 audio_extn_sound_trigger_stop_lab(in);
3237 in->standby = 1;
3238 }
3239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003241 if (adev->adm_deregister_stream)
3242 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3243
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003244 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003246 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3247 voice_extn_compress_voip_close_input_stream(stream);
3248 ALOGD("VOIP input entered standby");
3249 } else {
3250 if (in->pcm) {
3251 pcm_close(in->pcm);
3252 in->pcm = NULL;
3253 }
3254 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003255 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003256 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 }
3258 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003259 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 return status;
3261}
3262
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003263static int in_dump(const struct audio_stream *stream __unused,
3264 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265{
3266 return 0;
3267}
3268
3269static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3270{
3271 struct stream_in *in = (struct stream_in *)stream;
3272 struct audio_device *adev = in->dev;
3273 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003275 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303277 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 parms = str_parms_create_str(kvpairs);
3279
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303280 if (!parms)
3281 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003282 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003283 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003284
3285 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3286 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 val = atoi(value);
3288 /* no audio source uses val == 0 */
3289 if ((in->source != val) && (val != 0)) {
3290 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003291 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3292 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3293 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003294 (in->config.rate == 8000 || in->config.rate == 16000 ||
3295 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003296 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003297 err = voice_extn_compress_voip_open_input_stream(in);
3298 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003299 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003300 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003301 }
3302 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 }
3304 }
3305
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003306 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3307 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003309 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 in->device = val;
3311 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003312 if (!in->standby && !in->is_st_session) {
3313 ALOGV("update input routing change");
3314 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003315 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003316 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 }
3318 }
3319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003321 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322
3323 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303324error:
Eric Laurent994a6932013-07-17 11:51:42 -07003325 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326 return ret;
3327}
3328
3329static char* in_get_parameters(const struct audio_stream *stream,
3330 const char *keys)
3331{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003332 struct stream_in *in = (struct stream_in *)stream;
3333 struct str_parms *query = str_parms_create_str(keys);
3334 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003335 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003336
3337 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003338 if (reply) {
3339 str_parms_destroy(reply);
3340 }
3341 if (query) {
3342 str_parms_destroy(query);
3343 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003344 ALOGE("in_get_parameters: failed to create query or reply");
3345 return NULL;
3346 }
3347
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003348 ALOGV("%s: enter: keys - %s", __func__, keys);
3349
3350 voice_extn_in_get_parameters(in, query, reply);
3351
3352 str = str_parms_to_str(reply);
3353 str_parms_destroy(query);
3354 str_parms_destroy(reply);
3355
3356 ALOGV("%s: exit: returns - %s", __func__, str);
3357 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358}
3359
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003360static int in_set_gain(struct audio_stream_in *stream __unused,
3361 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362{
3363 return 0;
3364}
3365
3366static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3367 size_t bytes)
3368{
3369 struct stream_in *in = (struct stream_in *)stream;
3370 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303371 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303372 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303373 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003375 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303376
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003377 if (in->is_st_session) {
3378 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3379 /* Read from sound trigger HAL */
3380 audio_extn_sound_trigger_read(in, buffer, bytes);
3381 pthread_mutex_unlock(&in->lock);
3382 return bytes;
3383 }
3384
Ashish Jainbbce4322016-02-16 13:25:27 +05303385 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003386 ALOGD(" %s: sound card is not active/SSR state", __func__);
3387 ret= -EIO;;
3388 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303389 }
3390
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003392 pthread_mutex_lock(&adev->lock);
3393 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3394 ret = voice_extn_compress_voip_start_input_stream(in);
3395 else
3396 ret = start_input_stream(in);
3397 pthread_mutex_unlock(&adev->lock);
3398 if (ret != 0) {
3399 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 }
3401 in->standby = 0;
3402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003404 // what's the duration requested by the client?
3405 long ns = 0;
3406
3407 if (in->config.rate)
3408 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3409 in->config.rate;
3410
3411 request_in_focus(in, ns);
3412 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303415 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003416 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303417 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003418 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003419 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003420 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303421 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003422 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303423 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3424 if (bytes % 4 == 0) {
3425 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3426 int_buf_stream = buffer;
3427 for (size_t itt=0; itt < bytes/4 ; itt++) {
3428 int_buf_stream[itt] >>= 8;
3429 }
3430 } else {
3431 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3432 ret = -EINVAL;
3433 goto exit;
3434 }
3435 } if (ret < 0) {
3436 ret = -errno;
3437 }
3438 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 }
3440
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003441 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443 /*
3444 * Instead of writing zeroes here, we could trust the hardware
3445 * to always provide zeroes when muted.
3446 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303447 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3448 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 memset(buffer, 0, bytes);
3450
3451exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303452 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303453 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003454 if (-ENETRESET == ret)
3455 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457 pthread_mutex_unlock(&in->lock);
3458
3459 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303460 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303461 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303462 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303463 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303464 in->standby = true;
3465 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303466 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003468 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303469 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303470 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003471 }
3472 return bytes;
3473}
3474
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003475static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476{
3477 return 0;
3478}
3479
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003480static int add_remove_audio_effect(const struct audio_stream *stream,
3481 effect_handle_t effect,
3482 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003484 struct stream_in *in = (struct stream_in *)stream;
3485 int status = 0;
3486 effect_descriptor_t desc;
3487
3488 status = (*effect)->get_descriptor(effect, &desc);
3489 if (status != 0)
3490 return status;
3491
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003492 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003493 pthread_mutex_lock(&in->dev->lock);
3494 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3495 in->enable_aec != enable &&
3496 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3497 in->enable_aec = enable;
3498 if (!in->standby)
3499 select_devices(in->dev, in->usecase);
3500 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003501 if (in->enable_ns != enable &&
3502 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3503 in->enable_ns = enable;
3504 if (!in->standby)
3505 select_devices(in->dev, in->usecase);
3506 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003507 pthread_mutex_unlock(&in->dev->lock);
3508 pthread_mutex_unlock(&in->lock);
3509
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 return 0;
3511}
3512
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003513static int in_add_audio_effect(const struct audio_stream *stream,
3514 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515{
Eric Laurent994a6932013-07-17 11:51:42 -07003516 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003517 return add_remove_audio_effect(stream, effect, true);
3518}
3519
3520static int in_remove_audio_effect(const struct audio_stream *stream,
3521 effect_handle_t effect)
3522{
Eric Laurent994a6932013-07-17 11:51:42 -07003523 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003524 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525}
3526
3527static int adev_open_output_stream(struct audio_hw_device *dev,
3528 audio_io_handle_t handle,
3529 audio_devices_t devices,
3530 audio_output_flags_t flags,
3531 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003532 struct audio_stream_out **stream_out,
3533 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534{
3535 struct audio_device *adev = (struct audio_device *)dev;
3536 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303537 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003538 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303541
3542 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3543 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003544 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303545 return -EINVAL;
3546 }
3547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3549
Mingming Yin3a941d42016-02-17 18:08:05 -08003550 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3551 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303552 devices, flags, &out->stream);
3553
3554
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003555 if (!out) {
3556 return -ENOMEM;
3557 }
3558
Haynes Mathew George204045b2015-02-25 20:32:03 -08003559 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003560 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003561 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 if (devices == AUDIO_DEVICE_NONE)
3564 devices = AUDIO_DEVICE_OUT_SPEAKER;
3565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003566 out->flags = flags;
3567 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003568 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003569 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003570 out->sample_rate = config->sample_rate;
3571 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3572 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003573 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003574 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003575 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303576 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577
Mingming Yin3a941d42016-02-17 18:08:05 -08003578 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3579 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3580 pthread_mutex_lock(&adev->lock);
3581 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3582 ret = read_hdmi_sink_caps(out);
3583 pthread_mutex_unlock(&adev->lock);
3584 if (ret != 0) {
3585 if (ret == -ENOSYS) {
3586 /* ignore and go with default */
3587 ret = 0;
3588 } else {
3589 ALOGE("error reading hdmi sink caps");
3590 goto error_open;
3591 }
3592 }
3593 }
3594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003596 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303597 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3598 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003599 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3600 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3601
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003602 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003603 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3604 /*
3605 * Do not handle stereo output in Multi-channel cases
3606 * Stereo case is handled in normal playback path
3607 */
3608 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3609 ret = AUDIO_CHANNEL_OUT_STEREO;
3610 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003611
3612 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3613 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003614 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003615 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003616 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003617
3618 if (config->sample_rate == 0)
3619 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3620 if (config->channel_mask == 0)
3621 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003622 if (config->format == 0)
3623 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003624
3625 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003626 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003627 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3629 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003631 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003633 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3634 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003635 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003636 ret = voice_extn_compress_voip_open_output_stream(out);
3637 if (ret != 0) {
3638 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3639 __func__, ret);
3640 goto error_open;
3641 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003642 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3643 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3644
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003645 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3646 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3647 ALOGE("%s: Unsupported Offload information", __func__);
3648 ret = -EINVAL;
3649 goto error_open;
3650 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003651
Mingming Yin3a941d42016-02-17 18:08:05 -08003652 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003653 if(config->offload_info.format == 0)
3654 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003655 if (config->offload_info.sample_rate == 0)
3656 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003657 }
3658
Mingming Yin90310102013-11-13 16:57:00 -08003659 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303660 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003661 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 ret = -EINVAL;
3663 goto error_open;
3664 }
3665
3666 out->compr_config.codec = (struct snd_codec *)
3667 calloc(1, sizeof(struct snd_codec));
3668
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003669 if (!out->compr_config.codec) {
3670 ret = -ENOMEM;
3671 goto error_open;
3672 }
3673
vivek mehta0ea887a2015-08-26 14:01:20 -07003674 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303675 out->stream.pause = out_pause;
3676 out->stream.flush = out_flush;
3677 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003678 out->usecase = get_offload_usecase(adev, true);
3679 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003680 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003681 out->stream.set_callback = out_set_callback;
3682 out->stream.pause = out_pause;
3683 out->stream.resume = out_resume;
3684 out->stream.drain = out_drain;
3685 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003686 out->usecase = get_offload_usecase(adev, false);
3687 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003688 }
vivek mehta446c3962015-09-14 10:57:35 -07003689
3690 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003691 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3692 config->format == 0 && config->sample_rate == 0 &&
3693 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003694 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003695 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3696 } else {
3697 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3698 ret = -EEXIST;
3699 goto error_open;
3700 }
vivek mehta446c3962015-09-14 10:57:35 -07003701 }
3702
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 if (config->offload_info.channel_mask)
3704 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003705 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003706 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003707 config->offload_info.channel_mask = config->channel_mask;
3708 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003709 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003710 out->sample_rate = config->offload_info.sample_rate;
3711
Mingming Yin3ee55c62014-08-04 14:23:35 -07003712 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003713
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303714 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3715 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3716 audio_extn_dolby_send_ddp_endp_params(adev);
3717 audio_extn_dolby_set_dmid(adev);
3718 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003719
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003720 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003721 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003722 out->compr_config.codec->bit_rate =
3723 config->offload_info.bit_rate;
3724 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003725 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003726 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303727 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003728 /*TODO: Do we need to change it for passthrough */
3729 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003730
Manish Dewangana6fc5442015-08-24 20:30:31 +05303731 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3732 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3733 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3734 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303735
3736 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3737 AUDIO_FORMAT_PCM) {
3738
3739 /*Based on platform support, configure appropriate alsa format for corresponding
3740 *hal input format.
3741 */
3742 out->compr_config.codec->format = hal_format_to_alsa(
3743 config->offload_info.format);
3744
Ashish Jain83a6cc22016-06-28 14:34:17 +05303745 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303746 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303747 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303748
3749 /*for direct PCM playback populate bit_width based on selected alsa format as
3750 *hal input format and alsa format might differ based on platform support.
3751 */
3752 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303753 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303754
3755 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3756
3757 /* Check if alsa session is configured with the same format as HAL input format,
3758 * if not then derive correct fragment size needed to accomodate the
3759 * conversion of HAL input format to alsa format.
3760 */
3761 audio_extn_utils_update_direct_pcm_fragment_size(out);
3762
3763 /*if hal input and output fragment size is different this indicates HAL input format is
3764 *not same as the alsa format
3765 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303766 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303767 /*Allocate a buffer to convert input data to the alsa configured format.
3768 *size of convert buffer is equal to the size required to hold one fragment size
3769 *worth of pcm data, this is because flinger does not write more than fragment_size
3770 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303771 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3772 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303773 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3774 ret = -ENOMEM;
3775 goto error_open;
3776 }
3777 }
3778 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3779 out->compr_config.fragment_size =
3780 audio_extn_passthru_get_buffer_size(&config->offload_info);
3781 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3782 } else {
3783 out->compr_config.fragment_size =
3784 platform_get_compress_offload_buffer_size(&config->offload_info);
3785 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3786 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003787
Amit Shekhar6f461b12014-08-01 14:52:58 -07003788 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303789 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003790
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003791 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3792 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003793
Alexy Josephaa54c872014-12-03 02:46:47 -08003794
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003795 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303796 out->send_next_track_params = false;
3797 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003798 out->offload_state = OFFLOAD_STATE_IDLE;
3799 out->playback_started = 0;
3800
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003801 audio_extn_dts_create_state_notifier_node(out->usecase);
3802
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003803 create_offload_callback_thread(out);
3804 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3805 __func__, config->offload_info.version,
3806 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303807
3808 /* Disable gapless if any of the following is true
3809 * passthrough playback
3810 * AV playback
3811 * Direct PCM playback
3812 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303813 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303814 config->offload_info.has_video ||
3815 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3816 check_and_set_gapless_mode(adev, false);
3817 } else
3818 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003819
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303820 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003821 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3822 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003823 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303824 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003825 if (ret != 0) {
3826 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3827 __func__, ret);
3828 goto error_open;
3829 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003830 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3831 if (config->sample_rate == 0)
3832 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3833 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3834 config->sample_rate != 8000) {
3835 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3836 ret = -EINVAL;
3837 goto error_open;
3838 }
3839 out->sample_rate = config->sample_rate;
3840 out->config.rate = config->sample_rate;
3841 if (config->format == AUDIO_FORMAT_DEFAULT)
3842 config->format = AUDIO_FORMAT_PCM_16_BIT;
3843 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3844 config->format = AUDIO_FORMAT_PCM_16_BIT;
3845 ret = -EINVAL;
3846 goto error_open;
3847 }
3848 out->format = config->format;
3849 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3850 out->config = pcm_config_afe_proxy_playback;
3851 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003852 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303853 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3854 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003855 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3856 out->flags);
3857 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303858 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3859 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3860 out->config = pcm_config_low_latency;
3861 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3862 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3863 out->config = pcm_config_deep_buffer;
3864 } else {
3865 /* primary path is the default path selected if no other outputs are available/suitable */
3866 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3867 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3868 }
3869 out->hal_ip_format = format = out->format;
3870 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3871 out->hal_op_format = pcm_format_to_hal(out->config.format);
3872 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3873 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003874 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303875 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3876 if (out->hal_ip_format != out->hal_op_format) {
3877 uint32_t buffer_size = out->config.period_size *
3878 format_to_bitwidth_table[out->hal_op_format] *
3879 out->config.channels;
3880 out->convert_buffer = calloc(1, buffer_size);
3881 if (out->convert_buffer == NULL){
3882 ALOGE("Allocation failed for convert buffer for size %d",
3883 out->compr_config.fragment_size);
3884 ret = -ENOMEM;
3885 goto error_open;
3886 }
3887 ALOGD("Convert buffer allocated of size %d", buffer_size);
3888 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 }
3890
Ashish Jain83a6cc22016-06-28 14:34:17 +05303891 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3892 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3893
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003894 /* TODO remove this hardcoding and check why width is zero*/
3895 if (out->bit_width == 0)
3896 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003897 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3898 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003899 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303900 out->bit_width, out->channel_mask,
3901 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003902 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3903 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3904 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003905 if(adev->primary_output == NULL)
3906 adev->primary_output = out;
3907 else {
3908 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003909 ret = -EEXIST;
3910 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003911 }
3912 }
3913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 /* Check if this usecase is already existing */
3915 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003916 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3917 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003920 ret = -EEXIST;
3921 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922 }
3923 pthread_mutex_unlock(&adev->lock);
3924
3925 out->stream.common.get_sample_rate = out_get_sample_rate;
3926 out->stream.common.set_sample_rate = out_set_sample_rate;
3927 out->stream.common.get_buffer_size = out_get_buffer_size;
3928 out->stream.common.get_channels = out_get_channels;
3929 out->stream.common.get_format = out_get_format;
3930 out->stream.common.set_format = out_set_format;
3931 out->stream.common.standby = out_standby;
3932 out->stream.common.dump = out_dump;
3933 out->stream.common.set_parameters = out_set_parameters;
3934 out->stream.common.get_parameters = out_get_parameters;
3935 out->stream.common.add_audio_effect = out_add_audio_effect;
3936 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3937 out->stream.get_latency = out_get_latency;
3938 out->stream.set_volume = out_set_volume;
3939 out->stream.write = out_write;
3940 out->stream.get_render_position = out_get_render_position;
3941 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003942 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003944 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003946 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003947 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948
3949 config->format = out->stream.common.get_format(&out->stream.common);
3950 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3951 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3952
3953 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303954 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003955 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003956
3957 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3958 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3959 popcount(out->channel_mask), out->playback_started);
3960
Eric Laurent994a6932013-07-17 11:51:42 -07003961 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003963
3964error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303965 if (out->convert_buffer)
3966 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003967 free(out);
3968 *stream_out = NULL;
3969 ALOGD("%s: exit: ret %d", __func__, ret);
3970 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971}
3972
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003973static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003974 struct audio_stream_out *stream)
3975{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976 struct stream_out *out = (struct stream_out *)stream;
3977 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003978 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003979
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303980 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3981
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003982 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303983 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003984 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303985 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003986 if(ret != 0)
3987 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3988 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003989 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003990 out_standby(&stream->common);
3991
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003992 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003993 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003994 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003995 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003996 if (out->compr_config.codec != NULL)
3997 free(out->compr_config.codec);
3998 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003999
Ashish Jain83a6cc22016-06-28 14:34:17 +05304000 if (out->convert_buffer != NULL) {
4001 free(out->convert_buffer);
4002 out->convert_buffer = NULL;
4003 }
4004
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004005 if (adev->voice_tx_output == out)
4006 adev->voice_tx_output = NULL;
4007
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004008 pthread_cond_destroy(&out->cond);
4009 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004010 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004011 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012}
4013
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004014static void close_compress_sessions(struct audio_device *adev)
4015{
Mingming Yin7b762e72015-03-04 13:47:32 -08004016 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304017 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004018 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004019 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304020
4021 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004022 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304023 if (is_offload_usecase(usecase->id)) {
4024 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004025 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4026 out = usecase->stream.out;
4027 pthread_mutex_unlock(&adev->lock);
4028 out_standby(&out->stream.common);
4029 pthread_mutex_lock(&adev->lock);
4030 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304031 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004032 }
4033 pthread_mutex_unlock(&adev->lock);
4034}
4035
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4037{
4038 struct audio_device *adev = (struct audio_device *)dev;
4039 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004041 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004042 int ret;
4043 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004045 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304048 if (!parms)
4049 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004050 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4051 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304052 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304053 if (strstr(snd_card_status, "OFFLINE")) {
4054 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304055 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004056 //close compress sessions on OFFLINE status
4057 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304058 } else if (strstr(snd_card_status, "ONLINE")) {
4059 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304060 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004061 //send dts hpx license if enabled
4062 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304063 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304064 }
4065
4066 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004067 status = voice_set_parameters(adev, parms);
4068 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004069 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004071 status = platform_set_parameters(adev->platform, parms);
4072 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004073 goto done;
4074
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004075 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4076 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004077 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4079 adev->bluetooth_nrec = true;
4080 else
4081 adev->bluetooth_nrec = false;
4082 }
4083
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004084 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4085 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4087 adev->screen_off = false;
4088 else
4089 adev->screen_off = true;
4090 }
4091
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004092 ret = str_parms_get_int(parms, "rotation", &val);
4093 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004094 bool reverse_speakers = false;
4095 switch(val) {
4096 // FIXME: note that the code below assumes that the speakers are in the correct placement
4097 // relative to the user when the device is rotated 90deg from its default rotation. This
4098 // assumption is device-specific, not platform-specific like this code.
4099 case 270:
4100 reverse_speakers = true;
4101 break;
4102 case 0:
4103 case 90:
4104 case 180:
4105 break;
4106 default:
4107 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004108 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004109 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004110 if (status == 0) {
4111 if (adev->speaker_lr_swap != reverse_speakers) {
4112 adev->speaker_lr_swap = reverse_speakers;
4113 // only update the selected device if there is active pcm playback
4114 struct audio_usecase *usecase;
4115 struct listnode *node;
4116 list_for_each(node, &adev->usecase_list) {
4117 usecase = node_to_item(node, struct audio_usecase, list);
4118 if (usecase->type == PCM_PLAYBACK) {
4119 select_devices(adev, usecase->id);
4120 break;
4121 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004122 }
4123 }
4124 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004125 }
4126
Mingming Yin514a8bc2014-07-29 15:22:21 -07004127 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4128 if (ret >= 0) {
4129 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4130 adev->bt_wb_speech_enabled = true;
4131 else
4132 adev->bt_wb_speech_enabled = false;
4133 }
4134
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004135 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4136 if (ret >= 0) {
4137 val = atoi(value);
4138 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4139 ALOGV("cache new edid");
4140 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004141 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4142 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004143 /*
4144 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4145 * Per AudioPolicyManager, USB device is higher priority than WFD.
4146 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4147 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4148 * starting voice call on USB
4149 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004150 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4151 if (ret >= 0) {
4152 audio_extn_usb_add_device(val, atoi(value));
4153 }
vivek mehta344576a2016-04-12 18:56:03 -07004154 ALOGV("detected USB connect .. disable proxy");
4155 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004156 }
4157 }
4158
4159 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4160 if (ret >= 0) {
4161 val = atoi(value);
4162 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4163 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004164 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004165 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4166 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4167 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4168 if (ret >= 0) {
4169 audio_extn_usb_remove_device(val, atoi(value));
4170 }
vivek mehta344576a2016-04-12 18:56:03 -07004171 ALOGV("detected USB disconnect .. enable proxy");
4172 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004173 }
4174 }
4175
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004176 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004177
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004178done:
4179 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004180 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304181error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004182 ALOGV("%s: exit with code(%d)", __func__, status);
4183 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184}
4185
4186static char* adev_get_parameters(const struct audio_hw_device *dev,
4187 const char *keys)
4188{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004189 struct audio_device *adev = (struct audio_device *)dev;
4190 struct str_parms *reply = str_parms_create();
4191 struct str_parms *query = str_parms_create_str(keys);
4192 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304193 char value[256] = {0};
4194 int ret = 0;
4195
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004196 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004197 if (reply) {
4198 str_parms_destroy(reply);
4199 }
4200 if (query) {
4201 str_parms_destroy(query);
4202 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004203 ALOGE("adev_get_parameters: failed to create query or reply");
4204 return NULL;
4205 }
4206
Naresh Tannirud7205b62014-06-20 02:54:48 +05304207 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4208 sizeof(value));
4209 if (ret >=0) {
4210 int val = 1;
4211 pthread_mutex_lock(&adev->snd_card_status.lock);
4212 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4213 val = 0;
4214 pthread_mutex_unlock(&adev->snd_card_status.lock);
4215 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4216 goto exit;
4217 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004218
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004219 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004220 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004221 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004222 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304223 pthread_mutex_unlock(&adev->lock);
4224
Naresh Tannirud7205b62014-06-20 02:54:48 +05304225exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004226 str = str_parms_to_str(reply);
4227 str_parms_destroy(query);
4228 str_parms_destroy(reply);
4229
4230 ALOGV("%s: exit: returns - %s", __func__, str);
4231 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232}
4233
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004234static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235{
4236 return 0;
4237}
4238
4239static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4240{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004241 int ret;
4242 struct audio_device *adev = (struct audio_device *)dev;
4243 pthread_mutex_lock(&adev->lock);
4244 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004245 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004246 pthread_mutex_unlock(&adev->lock);
4247 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248}
4249
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004250static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4251 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252{
4253 return -ENOSYS;
4254}
4255
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004256static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4257 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258{
4259 return -ENOSYS;
4260}
4261
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004262static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4263 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004264{
4265 return -ENOSYS;
4266}
4267
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004268static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4269 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270{
4271 return -ENOSYS;
4272}
4273
4274static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4275{
4276 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004278 pthread_mutex_lock(&adev->lock);
4279 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004280 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004282 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004283 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004284 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004285 adev->current_call_output = NULL;
4286 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004287 }
4288 pthread_mutex_unlock(&adev->lock);
4289 return 0;
4290}
4291
4292static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4293{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004294 int ret;
4295
4296 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004297 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004298 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4299 pthread_mutex_unlock(&adev->lock);
4300
4301 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302}
4303
4304static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4305{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004306 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 return 0;
4308}
4309
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004310static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311 const struct audio_config *config)
4312{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004313 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004315 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4316 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004317}
4318
4319static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004320 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 audio_devices_t devices,
4322 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004323 struct audio_stream_in **stream_in,
4324 audio_input_flags_t flags __unused,
4325 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004326 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327{
4328 struct audio_device *adev = (struct audio_device *)dev;
4329 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004330 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004331 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004332 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304335 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4336 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304338 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339
4340 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004341
4342 if (!in) {
4343 ALOGE("failed to allocate input stream");
4344 return -ENOMEM;
4345 }
4346
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304347 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304348 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4349 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004350 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004351 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 in->stream.common.get_sample_rate = in_get_sample_rate;
4354 in->stream.common.set_sample_rate = in_set_sample_rate;
4355 in->stream.common.get_buffer_size = in_get_buffer_size;
4356 in->stream.common.get_channels = in_get_channels;
4357 in->stream.common.get_format = in_get_format;
4358 in->stream.common.set_format = in_set_format;
4359 in->stream.common.standby = in_standby;
4360 in->stream.common.dump = in_dump;
4361 in->stream.common.set_parameters = in_set_parameters;
4362 in->stream.common.get_parameters = in_get_parameters;
4363 in->stream.common.add_audio_effect = in_add_audio_effect;
4364 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4365 in->stream.set_gain = in_set_gain;
4366 in->stream.read = in_read;
4367 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4368
4369 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004370 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372 in->standby = 1;
4373 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004374 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004375 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376
4377 /* Update config params with the requested sample rate and channels */
4378 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004379 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4380 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4381 is_low_latency = true;
4382#if LOW_LATENCY_CAPTURE_USE_CASE
4383 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4384#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004385 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004386 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004387
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004388 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004389 if (in->realtime) {
4390 in->config = pcm_config_audio_capture_rt;
4391 in->sample_rate = in->config.rate;
4392 in->af_period_multiplier = af_period_multiplier;
4393 } else {
4394 in->config = pcm_config_audio_capture;
4395 in->config.rate = config->sample_rate;
4396 in->sample_rate = config->sample_rate;
4397 in->af_period_multiplier = 1;
4398 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304399 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004401 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304402 if (adev->mode != AUDIO_MODE_IN_CALL) {
4403 ret = -EINVAL;
4404 goto err_open;
4405 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004406 if (config->sample_rate == 0)
4407 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4408 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4409 config->sample_rate != 8000) {
4410 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4411 ret = -EINVAL;
4412 goto err_open;
4413 }
4414 if (config->format == AUDIO_FORMAT_DEFAULT)
4415 config->format = AUDIO_FORMAT_PCM_16_BIT;
4416 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4417 config->format = AUDIO_FORMAT_PCM_16_BIT;
4418 ret = -EINVAL;
4419 goto err_open;
4420 }
4421
4422 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4423 in->config = pcm_config_afe_proxy_record;
4424 in->config.channels = channel_count;
4425 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304426 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304427 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4428 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004429 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004430 audio_extn_compr_cap_format_supported(config->format) &&
4431 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004432 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004433 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304434 /* restrict 24 bit capture for unprocessed source only
4435 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4436 */
4437 if (config->format == AUDIO_FORMAT_DEFAULT) {
4438 config->format = AUDIO_FORMAT_PCM_16_BIT;
4439 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4440 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4441 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4442 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4443 bool ret_error = false;
4444 in->bit_width = 24;
4445 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4446 from HAL is 24_packed and 8_24
4447 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4448 24_packed return error indicating supported format is 24_packed
4449 *> In case of any other source requesting 24 bit or float return error
4450 indicating format supported is 16 bit only.
4451
4452 on error flinger will retry with supported format passed
4453 */
4454 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4455 (source != AUDIO_SOURCE_CAMCORDER)) {
4456 config->format = AUDIO_FORMAT_PCM_16_BIT;
4457 if( config->sample_rate > 48000)
4458 config->sample_rate = 48000;
4459 ret_error = true;
4460 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4461 in->config.format = PCM_FORMAT_S24_3LE;
4462 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4463 in->config.format = PCM_FORMAT_S24_LE;
4464 } else {
4465 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4466 ret_error = true;
4467 }
4468
4469 if (ret_error) {
4470 ret = -EINVAL;
4471 goto err_open;
4472 }
4473 }
4474
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004475 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004476 if (!in->realtime) {
4477 in->format = config->format;
4478 frame_size = audio_stream_in_frame_size(&in->stream);
4479 buffer_size = get_input_buffer_size(config->sample_rate,
4480 config->format,
4481 channel_count,
4482 is_low_latency);
4483 in->config.period_size = buffer_size / frame_size;
4484 }
4485
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004486 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4487 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4488 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004489 (in->config.rate == 8000 || in->config.rate == 16000 ||
4490 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004491 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4492 voice_extn_compress_voip_open_input_stream(in);
4493 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004496 /* This stream could be for sound trigger lab,
4497 get sound trigger pcm if present */
4498 audio_extn_sound_trigger_check_and_get_session(in);
4499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004501 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004502 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503
4504err_open:
4505 free(in);
4506 *stream_in = NULL;
4507 return ret;
4508}
4509
4510static void adev_close_input_stream(struct audio_hw_device *dev,
4511 struct audio_stream_in *stream)
4512{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004513 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004514 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004515 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304516
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304517 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004518
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304519 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004520 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304521
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004522 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304523 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004524 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304525 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004526 if (ret != 0)
4527 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4528 __func__, ret);
4529 } else
4530 in_standby(&stream->common);
4531
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004532 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004533 audio_extn_ssr_deinit();
4534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535
Mingming Yine62d7842013-10-25 16:26:03 -07004536 if(audio_extn_compr_cap_enabled() &&
4537 audio_extn_compr_cap_format_supported(in->config.format))
4538 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004539
Mingming Yinfd7607b2016-01-22 12:48:44 -08004540 if (in->is_st_session) {
4541 ALOGV("%s: sound trigger pcm stop lab", __func__);
4542 audio_extn_sound_trigger_stop_lab(in);
4543 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004544 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545 return;
4546}
4547
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004548static int adev_dump(const audio_hw_device_t *device __unused,
4549 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550{
4551 return 0;
4552}
4553
4554static int adev_close(hw_device_t *device)
4555{
4556 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004557
4558 if (!adev)
4559 return 0;
4560
4561 pthread_mutex_lock(&adev_init_lock);
4562
4563 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004564 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004565 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004566 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004567 audio_route_free(adev->audio_route);
4568 free(adev->snd_dev_ref_cnt);
4569 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004570 if (adev->adm_deinit)
4571 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004572 free(device);
4573 adev = NULL;
4574 }
4575 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577 return 0;
4578}
4579
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004580/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4581 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4582 * just that it _might_ work.
4583 */
4584static int period_size_is_plausible_for_low_latency(int period_size)
4585{
4586 switch (period_size) {
4587 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004588 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004589 case 240:
4590 case 320:
4591 case 480:
4592 return 1;
4593 default:
4594 return 0;
4595 }
4596}
4597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598static int adev_open(const hw_module_t *module, const char *name,
4599 hw_device_t **device)
4600{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004601 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4603
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004604 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004605 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004606 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004607 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004608 ALOGD("%s: returning existing instance of adev", __func__);
4609 ALOGD("%s: exit", __func__);
4610 pthread_mutex_unlock(&adev_init_lock);
4611 return 0;
4612 }
4613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 adev = calloc(1, sizeof(struct audio_device));
4615
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004616 if (!adev) {
4617 pthread_mutex_unlock(&adev_init_lock);
4618 return -ENOMEM;
4619 }
4620
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004621 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4624 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4625 adev->device.common.module = (struct hw_module_t *)module;
4626 adev->device.common.close = adev_close;
4627
4628 adev->device.init_check = adev_init_check;
4629 adev->device.set_voice_volume = adev_set_voice_volume;
4630 adev->device.set_master_volume = adev_set_master_volume;
4631 adev->device.get_master_volume = adev_get_master_volume;
4632 adev->device.set_master_mute = adev_set_master_mute;
4633 adev->device.get_master_mute = adev_get_master_mute;
4634 adev->device.set_mode = adev_set_mode;
4635 adev->device.set_mic_mute = adev_set_mic_mute;
4636 adev->device.get_mic_mute = adev_get_mic_mute;
4637 adev->device.set_parameters = adev_set_parameters;
4638 adev->device.get_parameters = adev_get_parameters;
4639 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4640 adev->device.open_output_stream = adev_open_output_stream;
4641 adev->device.close_output_stream = adev_close_output_stream;
4642 adev->device.open_input_stream = adev_open_input_stream;
4643 adev->device.close_input_stream = adev_close_input_stream;
4644 adev->device.dump = adev_dump;
4645
4646 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004648 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004649 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004652 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004653 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004654 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004655 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004656 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004657 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004658 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004659 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304660 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304661 adev->perf_lock_opts[0] = 0x101;
4662 adev->perf_lock_opts[1] = 0x20E;
4663 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304664
4665 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4666 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004668 adev->platform = platform_init(adev);
4669 if (!adev->platform) {
4670 free(adev->snd_dev_ref_cnt);
4671 free(adev);
4672 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4673 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004674 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004675 return -EINVAL;
4676 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004677
Naresh Tanniru4c630392014-05-12 01:05:52 +05304678 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4679
Eric Laurentc4aef752013-09-12 17:45:53 -07004680 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4681 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4682 if (adev->visualizer_lib == NULL) {
4683 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4684 } else {
4685 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4686 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004687 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004688 "visualizer_hal_start_output");
4689 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004690 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004691 "visualizer_hal_stop_output");
4692 }
4693 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004694 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004695 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004696
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004697 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4698 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4699 if (adev->offload_effects_lib == NULL) {
4700 ALOGE("%s: DLOPEN failed for %s", __func__,
4701 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4702 } else {
4703 ALOGV("%s: DLOPEN successful for %s", __func__,
4704 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4705 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304706 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004707 "offload_effects_bundle_hal_start_output");
4708 adev->offload_effects_stop_output =
4709 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4710 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004711 adev->offload_effects_set_hpx_state =
4712 (int (*)(bool))dlsym(adev->offload_effects_lib,
4713 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304714 adev->offload_effects_get_parameters =
4715 (void (*)(struct str_parms *, struct str_parms *))
4716 dlsym(adev->offload_effects_lib,
4717 "offload_effects_bundle_get_parameters");
4718 adev->offload_effects_set_parameters =
4719 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4720 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004721 }
4722 }
4723
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004724 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4725 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4726 if (adev->adm_lib == NULL) {
4727 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4728 } else {
4729 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4730 adev->adm_init = (adm_init_t)
4731 dlsym(adev->adm_lib, "adm_init");
4732 adev->adm_deinit = (adm_deinit_t)
4733 dlsym(adev->adm_lib, "adm_deinit");
4734 adev->adm_register_input_stream = (adm_register_input_stream_t)
4735 dlsym(adev->adm_lib, "adm_register_input_stream");
4736 adev->adm_register_output_stream = (adm_register_output_stream_t)
4737 dlsym(adev->adm_lib, "adm_register_output_stream");
4738 adev->adm_deregister_stream = (adm_deregister_stream_t)
4739 dlsym(adev->adm_lib, "adm_deregister_stream");
4740 adev->adm_request_focus = (adm_request_focus_t)
4741 dlsym(adev->adm_lib, "adm_request_focus");
4742 adev->adm_abandon_focus = (adm_abandon_focus_t)
4743 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004744 adev->adm_set_config = (adm_set_config_t)
4745 dlsym(adev->adm_lib, "adm_set_config");
4746 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4747 dlsym(adev->adm_lib, "adm_request_focus_v2");
4748 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4749 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4750 adev->adm_on_routing_change = (adm_on_routing_change_t)
4751 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004752 }
4753 }
4754
Mingming Yin514a8bc2014-07-29 15:22:21 -07004755 adev->bt_wb_speech_enabled = false;
4756
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004757 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 *device = &adev->device.common;
4759
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004760 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4761 &adev->streams_output_cfg_list);
4762
Kiran Kandi910e1862013-10-29 13:29:42 -07004763 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004764
4765 char value[PROPERTY_VALUE_MAX];
4766 int trial;
4767 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4768 trial = atoi(value);
4769 if (period_size_is_plausible_for_low_latency(trial)) {
4770 pcm_config_low_latency.period_size = trial;
4771 pcm_config_low_latency.start_threshold = trial / 4;
4772 pcm_config_low_latency.avail_min = trial / 4;
4773 configured_low_latency_capture_period_size = trial;
4774 }
4775 }
4776 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4777 trial = atoi(value);
4778 if (period_size_is_plausible_for_low_latency(trial)) {
4779 configured_low_latency_capture_period_size = trial;
4780 }
4781 }
4782
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004783 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4784 af_period_multiplier = atoi(value);
4785 if (af_period_multiplier < 0)
4786 af_period_multiplier = 2;
4787 else if (af_period_multiplier > 4)
4788 af_period_multiplier = 4;
4789
4790 ALOGV("new period_multiplier = %d", af_period_multiplier);
4791 }
4792
vivek mehta446c3962015-09-14 10:57:35 -07004793 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004794 pthread_mutex_unlock(&adev_init_lock);
4795
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004796 if (adev->adm_init)
4797 adev->adm_data = adev->adm_init();
4798
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304799 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004800 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801 return 0;
4802}
4803
4804static struct hw_module_methods_t hal_module_methods = {
4805 .open = adev_open,
4806};
4807
4808struct audio_module HAL_MODULE_INFO_SYM = {
4809 .common = {
4810 .tag = HARDWARE_MODULE_TAG,
4811 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4812 .hal_api_version = HARDWARE_HAL_API_VERSION,
4813 .id = AUDIO_HARDWARE_MODULE_ID,
4814 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004815 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816 .methods = &hal_module_methods,
4817 },
4818};