blob: 272d64b13464d9df58ac0a3aa767593fbf0db58f [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) &&
Avinash Vaish4d6167d2014-06-25 12:20:37 +05301217 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001218 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001219 in_snd_device = voip_usecase->in_snd_device;
1220 out_snd_device = voip_usecase->out_snd_device;
1221 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001222 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001223 hfp_ucid = audio_extn_hfp_get_usecase();
1224 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001225 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001226 in_snd_device = hfp_usecase->in_snd_device;
1227 out_snd_device = hfp_usecase->out_snd_device;
1228 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001229 }
1230 if (usecase->type == PCM_PLAYBACK) {
1231 usecase->devices = usecase->stream.out->devices;
1232 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001233 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001234 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001235 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001236 if (usecase->stream.out == adev->primary_output &&
1237 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001238 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001239 select_devices(adev, adev->active_input->usecase);
1240 }
1241 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242 } else if (usecase->type == PCM_CAPTURE) {
1243 usecase->devices = usecase->stream.in->device;
1244 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001245 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001246 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001247 if (adev->active_input &&
1248 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301249 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1250 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1251 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001252 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001253 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001254 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1255 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001256 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001257 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001258 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259 }
1260 }
1261
1262 if (out_snd_device == usecase->out_snd_device &&
1263 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301264
1265 if (!force_device_switch(usecase))
1266 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 }
1268
sangwoobc677242013-08-08 16:53:43 +09001269 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001270 out_snd_device, platform_get_snd_device_name(out_snd_device),
1271 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001272
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273 /*
1274 * Limitation: While in call, to do a device switch we need to disable
1275 * and enable both RX and TX devices though one of them is same as current
1276 * device.
1277 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001278 if ((usecase->type == VOICE_CALL) &&
1279 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1280 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001281 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001282 }
1283
1284 if (((usecase->type == VOICE_CALL) ||
1285 (usecase->type == VOIP_CALL)) &&
1286 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1287 /* Disable sidetone only if voice/voip call already exists */
1288 if (voice_is_call_state_active(adev) ||
1289 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001290 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001291 }
1292
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001293 /* Disable current sound devices */
1294 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001295 disable_audio_route(adev, usecase);
1296 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 }
1298
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001300 disable_audio_route(adev, usecase);
1301 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 }
1303
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001304 /* Applicable only on the targets that has external modem.
1305 * New device information should be sent to modem before enabling
1306 * the devices to reduce in-call device switch time.
1307 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001308 if ((usecase->type == VOICE_CALL) &&
1309 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1310 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001311 status = platform_switch_voice_call_enable_device_config(adev->platform,
1312 out_snd_device,
1313 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001314 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001315
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 /* Enable new sound devices */
1317 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001318 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001319 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001320 }
1321
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001322 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301323 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001324 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001325 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001326
Avinash Vaish71a8b972014-07-24 15:36:33 +05301327 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001328 status = platform_switch_voice_call_device_post(adev->platform,
1329 out_snd_device,
1330 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301331 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001332 /* Enable sidetone only if voice/voip call already exists */
1333 if (voice_is_call_state_active(adev) ||
1334 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001335 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301336 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001337
sangwoo170731f2013-06-08 15:36:36 +09001338 usecase->in_snd_device = in_snd_device;
1339 usecase->out_snd_device = out_snd_device;
1340
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301341 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001342 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301343 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001344 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301345 usecase->stream.out->flags,
1346 usecase->stream.out->format,
1347 usecase->stream.out->sample_rate,
1348 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301349 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301350 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001351 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301352 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001353
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001354 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001355
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001356 /* Applicable only on the targets that has external modem.
1357 * Enable device command should be sent to modem only after
1358 * enabling voice call mixer controls
1359 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001360 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001361 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1362 out_snd_device,
1363 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301364 ALOGD("%s: done",__func__);
1365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001366 return status;
1367}
1368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369static int stop_input_stream(struct stream_in *in)
1370{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301371 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 struct audio_usecase *uc_info;
1373 struct audio_device *adev = in->dev;
1374
Eric Laurentc8400632013-02-14 19:04:54 -08001375 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001376
Eric Laurent994a6932013-07-17 11:51:42 -07001377 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001378 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001379 uc_info = get_usecase_from_list(adev, in->usecase);
1380 if (uc_info == NULL) {
1381 ALOGE("%s: Could not find the usecase (%d) in the list",
1382 __func__, in->usecase);
1383 return -EINVAL;
1384 }
1385
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001386 /* Close in-call recording streams */
1387 voice_check_and_stop_incall_rec_usecase(adev, in);
1388
Eric Laurent150dbfe2013-02-27 14:31:02 -08001389 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001390 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391
1392 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001393 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001395 list_remove(&uc_info->list);
1396 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001397
Eric Laurent994a6932013-07-17 11:51:42 -07001398 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399 return ret;
1400}
1401
1402int start_input_stream(struct stream_in *in)
1403{
1404 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001405 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406 struct audio_usecase *uc_info;
1407 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301408 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409
Mingming Yin2664a5b2015-09-03 10:53:11 -07001410 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1411 if (get_usecase_from_list(adev, usecase) == NULL)
1412 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301413 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1414 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001415
Naresh Tanniru80659832014-06-04 18:17:56 +05301416
1417 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301418 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301419 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301420 goto error_config;
1421 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301422
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001423 /* Check if source matches incall recording usecase criteria */
1424 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1425 if (ret)
1426 goto error_config;
1427 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001428 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1429
1430 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1431 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1432 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001433 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001434 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001435
Eric Laurentb23d5282013-05-14 15:27:20 -07001436 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 if (in->pcm_device_id < 0) {
1438 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1439 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001440 ret = -EINVAL;
1441 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443
1444 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001446
1447 if (!uc_info) {
1448 ret = -ENOMEM;
1449 goto error_config;
1450 }
1451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 uc_info->id = in->usecase;
1453 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001454 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001455 uc_info->devices = in->device;
1456 uc_info->in_snd_device = SND_DEVICE_NONE;
1457 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001459 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301460 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1461 adev->perf_lock_opts,
1462 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301465 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1466 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001467
1468 unsigned int flags = PCM_IN;
1469 unsigned int pcm_open_retry_count = 0;
1470
1471 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1472 flags |= PCM_MMAP | PCM_NOIRQ;
1473 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001474 } else if (in->realtime) {
1475 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001476 }
1477
1478 while (1) {
1479 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1480 flags, &in->config);
1481 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1482 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1483 if (in->pcm != NULL) {
1484 pcm_close(in->pcm);
1485 in->pcm = NULL;
1486 }
1487 if (pcm_open_retry_count-- == 0) {
1488 ret = -EIO;
1489 goto error_open;
1490 }
1491 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1492 continue;
1493 }
1494 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001496
1497 ALOGV("%s: pcm_prepare", __func__);
1498 ret = pcm_prepare(in->pcm);
1499 if (ret < 0) {
1500 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1501 pcm_close(in->pcm);
1502 in->pcm = NULL;
1503 goto error_open;
1504 }
1505
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001506 register_in_stream(in);
1507 if (in->realtime) {
1508 ret = pcm_start(in->pcm);
1509 if (ret < 0)
1510 goto error_open;
1511 }
1512
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301513 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001514 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001515
Eric Laurentc8400632013-02-14 19:04:54 -08001516 return ret;
1517
1518error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301519 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001521error_config:
1522 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301523 /*
1524 * sleep 50ms to allow sufficient time for kernel
1525 * drivers to recover incases like SSR.
1526 */
1527 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001529
1530 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531}
1532
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001533void lock_input_stream(struct stream_in *in)
1534{
1535 pthread_mutex_lock(&in->pre_lock);
1536 pthread_mutex_lock(&in->lock);
1537 pthread_mutex_unlock(&in->pre_lock);
1538}
1539
1540void lock_output_stream(struct stream_out *out)
1541{
1542 pthread_mutex_lock(&out->pre_lock);
1543 pthread_mutex_lock(&out->lock);
1544 pthread_mutex_unlock(&out->pre_lock);
1545}
1546
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547/* must be called with out->lock locked */
1548static int send_offload_cmd_l(struct stream_out* out, int command)
1549{
1550 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1551
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001552 if (!cmd) {
1553 ALOGE("failed to allocate mem for command 0x%x", command);
1554 return -ENOMEM;
1555 }
1556
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001557 ALOGVV("%s %d", __func__, command);
1558
1559 cmd->cmd = command;
1560 list_add_tail(&out->offload_cmd_list, &cmd->node);
1561 pthread_cond_signal(&out->offload_cond);
1562 return 0;
1563}
1564
1565/* must be called iwth out->lock locked */
1566static void stop_compressed_output_l(struct stream_out *out)
1567{
1568 out->offload_state = OFFLOAD_STATE_IDLE;
1569 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001570 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001571 if (out->compr != NULL) {
1572 compress_stop(out->compr);
1573 while (out->offload_thread_blocked) {
1574 pthread_cond_wait(&out->cond, &out->lock);
1575 }
1576 }
1577}
1578
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001579bool is_offload_usecase(audio_usecase_t uc_id)
1580{
1581 unsigned int i;
1582 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1583 if (uc_id == offload_usecases[i])
1584 return true;
1585 }
1586 return false;
1587}
1588
vivek mehta446c3962015-09-14 10:57:35 -07001589static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001590{
vivek mehta446c3962015-09-14 10:57:35 -07001591 audio_usecase_t ret_uc = USECASE_INVALID;
1592 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001593 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001594 if (!adev->multi_offload_enable) {
1595 if (is_direct_pcm)
1596 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1597 else
1598 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001599
vivek mehta446c3962015-09-14 10:57:35 -07001600 pthread_mutex_lock(&adev->lock);
1601 if (get_usecase_from_list(adev, ret_uc) != NULL)
1602 ret_uc = USECASE_INVALID;
1603 pthread_mutex_unlock(&adev->lock);
1604
1605 return ret_uc;
1606 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001607
1608 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001609 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1610 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1611 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1612 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001613 break;
1614 }
1615 }
vivek mehta446c3962015-09-14 10:57:35 -07001616
1617 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1618 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001619}
1620
1621static void free_offload_usecase(struct audio_device *adev,
1622 audio_usecase_t uc_id)
1623{
vivek mehta446c3962015-09-14 10:57:35 -07001624 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001625 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001626
1627 if (!adev->multi_offload_enable)
1628 return;
1629
1630 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1631 if (offload_usecases[offload_uc_index] == uc_id) {
1632 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001633 break;
1634 }
1635 }
1636 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1637}
1638
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001639static void *offload_thread_loop(void *context)
1640{
1641 struct stream_out *out = (struct stream_out *) context;
1642 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001643 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001644
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1646 set_sched_policy(0, SP_FOREGROUND);
1647 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1648
1649 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001650 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001651 for (;;) {
1652 struct offload_cmd *cmd = NULL;
1653 stream_callback_event_t event;
1654 bool send_callback = false;
1655
1656 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1657 __func__, list_empty(&out->offload_cmd_list),
1658 out->offload_state);
1659 if (list_empty(&out->offload_cmd_list)) {
1660 ALOGV("%s SLEEPING", __func__);
1661 pthread_cond_wait(&out->offload_cond, &out->lock);
1662 ALOGV("%s RUNNING", __func__);
1663 continue;
1664 }
1665
1666 item = list_head(&out->offload_cmd_list);
1667 cmd = node_to_item(item, struct offload_cmd, node);
1668 list_remove(item);
1669
1670 ALOGVV("%s STATE %d CMD %d out->compr %p",
1671 __func__, out->offload_state, cmd->cmd, out->compr);
1672
1673 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1674 free(cmd);
1675 break;
1676 }
1677
1678 if (out->compr == NULL) {
1679 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001680 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 pthread_cond_signal(&out->cond);
1682 continue;
1683 }
1684 out->offload_thread_blocked = true;
1685 pthread_mutex_unlock(&out->lock);
1686 send_callback = false;
1687 switch(cmd->cmd) {
1688 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001689 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001690 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001691 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001692 send_callback = true;
1693 event = STREAM_CBK_EVENT_WRITE_READY;
1694 break;
1695 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001696 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301697 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001698 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301699 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001700 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301701 if (ret < 0)
1702 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301703 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301704 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001705 compress_drain(out->compr);
1706 else
1707 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301708 if (ret != -ENETRESET) {
1709 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301710 pthread_mutex_lock(&out->lock);
1711 out->send_new_metadata = 1;
1712 out->send_next_track_params = true;
1713 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301714 event = STREAM_CBK_EVENT_DRAIN_READY;
1715 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1716 } else
1717 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718 break;
1719 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001720 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001721 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001722 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723 send_callback = true;
1724 event = STREAM_CBK_EVENT_DRAIN_READY;
1725 break;
1726 default:
1727 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1728 break;
1729 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001730 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 out->offload_thread_blocked = false;
1732 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001733 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001734 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001735 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001736 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001737 free(cmd);
1738 }
1739
1740 pthread_cond_signal(&out->cond);
1741 while (!list_empty(&out->offload_cmd_list)) {
1742 item = list_head(&out->offload_cmd_list);
1743 list_remove(item);
1744 free(node_to_item(item, struct offload_cmd, node));
1745 }
1746 pthread_mutex_unlock(&out->lock);
1747
1748 return NULL;
1749}
1750
1751static int create_offload_callback_thread(struct stream_out *out)
1752{
1753 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1754 list_init(&out->offload_cmd_list);
1755 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1756 offload_thread_loop, out);
1757 return 0;
1758}
1759
1760static int destroy_offload_callback_thread(struct stream_out *out)
1761{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001762 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001763 stop_compressed_output_l(out);
1764 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1765
1766 pthread_mutex_unlock(&out->lock);
1767 pthread_join(out->offload_thread, (void **) NULL);
1768 pthread_cond_destroy(&out->offload_cond);
1769
1770 return 0;
1771}
1772
Mingming Yin21854652016-04-13 11:54:02 -07001773static bool allow_hdmi_channel_config(struct audio_device *adev,
1774 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001775{
1776 struct listnode *node;
1777 struct audio_usecase *usecase;
1778 bool ret = true;
1779
Mingming Yin21854652016-04-13 11:54:02 -07001780 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1781 ret = false;
1782 goto exit;
1783 }
1784
1785 if (audio_extn_passthru_is_active()) {
1786 ALOGI("%s: Compress audio passthrough is active,"
1787 "no HDMI config change allowed", __func__);
1788 ret = false;
1789 goto exit;
1790 }
1791
Eric Laurent07eeafd2013-10-06 12:52:49 -07001792 list_for_each(node, &adev->usecase_list) {
1793 usecase = node_to_item(node, struct audio_usecase, list);
1794 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1795 /*
1796 * If voice call is already existing, do not proceed further to avoid
1797 * disabling/enabling both RX and TX devices, CSD calls, etc.
1798 * Once the voice call done, the HDMI channels can be configured to
1799 * max channels of remaining use cases.
1800 */
1801 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001802 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001803 __func__);
1804 ret = false;
1805 break;
1806 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001807 if (!enable_passthru) {
1808 ALOGV("%s: multi channel playback is active, "
1809 "no change in HDMI channels", __func__);
1810 ret = false;
1811 break;
1812 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001813 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001814 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001815 if (!enable_passthru) {
1816 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1817 ", no change in HDMI channels", __func__,
1818 usecase->stream.out->channel_mask);
1819 ret = false;
1820 break;
1821 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001822 }
1823 }
1824 }
Mingming Yin21854652016-04-13 11:54:02 -07001825 ALOGV("allow hdmi config %d", ret);
1826exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001827 return ret;
1828}
1829
Mingming Yin21854652016-04-13 11:54:02 -07001830static int check_and_set_hdmi_config(struct audio_device *adev,
1831 uint32_t channels,
1832 uint32_t sample_rate,
1833 audio_format_t format,
1834 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001835{
1836 struct listnode *node;
1837 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001838 int32_t factor = 1;
1839 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001840
Mingming Yin21854652016-04-13 11:54:02 -07001841 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1842 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001843
Mingming Yin21854652016-04-13 11:54:02 -07001844 if (channels != adev->cur_hdmi_channels) {
1845 ALOGV("channel does not match current hdmi channels");
1846 config = true;
1847 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001848
Mingming Yin21854652016-04-13 11:54:02 -07001849 if (sample_rate != adev->cur_hdmi_sample_rate) {
1850 ALOGV("sample rate does not match current hdmi sample rate");
1851 config = true;
1852 }
1853
1854 if (format != adev->cur_hdmi_format) {
1855 ALOGV("format does not match current hdmi format");
1856 config = true;
1857 }
1858
1859 /* TBD - add check for bit width */
1860 if (!config) {
1861 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001862 return 0;
1863 }
1864
Mingming Yin21854652016-04-13 11:54:02 -07001865 if (enable_passthru &&
1866 (format == AUDIO_FORMAT_E_AC3)) {
1867 ALOGV("factor 4 for E_AC3 passthru");
1868 factor = 4;
1869 }
1870
1871 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1872 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001873 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001874 adev->cur_hdmi_format = format;
1875 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001876
1877 /*
1878 * Deroute all the playback streams routed to HDMI so that
1879 * the back end is deactivated. Note that backend will not
1880 * be deactivated if any one stream is connected to it.
1881 */
1882 list_for_each(node, &adev->usecase_list) {
1883 usecase = node_to_item(node, struct audio_usecase, list);
1884 if (usecase->type == PCM_PLAYBACK &&
1885 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001886 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001887 }
1888 }
1889
Mingming Yin21854652016-04-13 11:54:02 -07001890 bool was_active = audio_extn_keep_alive_is_active();
1891 if (was_active)
1892 audio_extn_keep_alive_stop();
1893
Eric Laurent07eeafd2013-10-06 12:52:49 -07001894 /*
1895 * Enable all the streams disabled above. Now the HDMI backend
1896 * will be activated with new channel configuration
1897 */
1898 list_for_each(node, &adev->usecase_list) {
1899 usecase = node_to_item(node, struct audio_usecase, list);
1900 if (usecase->type == PCM_PLAYBACK &&
1901 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001902 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001903 }
1904 }
1905
Mingming Yin21854652016-04-13 11:54:02 -07001906 if (was_active)
1907 audio_extn_keep_alive_start();
1908
Eric Laurent07eeafd2013-10-06 12:52:49 -07001909 return 0;
1910}
1911
Mingming Yin21854652016-04-13 11:54:02 -07001912/* called with out lock taken */
1913static int check_and_set_hdmi_backend(struct stream_out *out)
1914{
1915 struct audio_device *adev = out->dev;
1916 int ret;
1917 bool enable_passthru = false;
1918
1919 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1920 return -1;
1921
1922 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1923
1924 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301925 audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07001926 enable_passthru = true;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301927 ALOGV("%s : enable_passthru is set to true", __func__);
Mingming Yin21854652016-04-13 11:54:02 -07001928 }
1929
1930 /* Check if change in HDMI channel config is allowed */
1931 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1932 return -EPERM;
1933 }
1934
1935 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1936 uint32_t channels;
1937 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1938
1939 if (enable_passthru) {
1940 audio_extn_passthru_on_start(out);
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301941 audio_extn_passthru_update_stream_configuration(adev, out);
Mingming Yin21854652016-04-13 11:54:02 -07001942 }
1943
1944 /* For pass through case, the backend should be configured as stereo */
1945 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1946 out->compr_config.codec->ch_in;
1947
1948 ret = check_and_set_hdmi_config(adev, channels,
1949 out->sample_rate, out->format,
1950 enable_passthru);
1951 } else
1952 ret = check_and_set_hdmi_config(adev, out->config.channels,
1953 out->config.rate,
1954 out->format,
1955 false);
1956 return ret;
1957}
1958
1959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960static int stop_output_stream(struct stream_out *out)
1961{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301962 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963 struct audio_usecase *uc_info;
1964 struct audio_device *adev = out->dev;
1965
Eric Laurent994a6932013-07-17 11:51:42 -07001966 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001967 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 uc_info = get_usecase_from_list(adev, out->usecase);
1969 if (uc_info == NULL) {
1970 ALOGE("%s: Could not find the usecase (%d) in the list",
1971 __func__, out->usecase);
1972 return -EINVAL;
1973 }
1974
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001975 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301976 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001977 if (adev->visualizer_stop_output != NULL)
1978 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001979
1980 audio_extn_dts_remove_state_notifier_node(out->usecase);
1981
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001982 if (adev->offload_effects_stop_output != NULL)
1983 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1984 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001985
Eric Laurent150dbfe2013-02-27 14:31:02 -08001986 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001987 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001988
1989 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001990 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001992 list_remove(&uc_info->list);
1993 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001995 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301996 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001997 ALOGV("Disable passthrough , reset mixer to pcm");
1998 /* NO_PASSTHROUGH */
1999 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002000
Mingming Yin21854652016-04-13 11:54:02 -07002001 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002002 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2003 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002004
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302005 /* Must be called after removing the usecase from list */
2006 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2007 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
2008 DEFAULT_HDMI_OUT_SAMPLE_RATE,
2009 DEFAULT_HDMI_OUT_FORMAT,
2010 false);
Eric Laurent994a6932013-07-17 11:51:42 -07002011 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 return ret;
2013}
2014
2015int start_output_stream(struct stream_out *out)
2016{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018 struct audio_usecase *uc_info;
2019 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302020 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002022 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2023 ret = -EINVAL;
2024 goto error_config;
2025 }
2026
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302027 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2028 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2029 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302030
Naresh Tanniru80659832014-06-04 18:17:56 +05302031 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302032 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302033 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302034 goto error_config;
2035 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302036
Eric Laurentb23d5282013-05-14 15:27:20 -07002037 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038 if (out->pcm_device_id < 0) {
2039 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2040 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002041 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002042 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 }
2044
2045 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002046
2047 if (!uc_info) {
2048 ret = -ENOMEM;
2049 goto error_config;
2050 }
2051
Mingming Yin21854652016-04-13 11:54:02 -07002052 /* This must be called before adding this usecase to the list */
2053 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2054 /* This call can fail if compress pass thru is already active */
2055 check_and_set_hdmi_backend(out);
2056 }
2057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 uc_info->id = out->usecase;
2059 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002060 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002061 uc_info->devices = out->devices;
2062 uc_info->in_snd_device = SND_DEVICE_NONE;
2063 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002064 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002065
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302066 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2067 adev->perf_lock_opts,
2068 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 select_devices(adev, out->usecase);
2070
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002071 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2072 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002073 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002074 unsigned int flags = PCM_OUT;
2075 unsigned int pcm_open_retry_count = 0;
2076 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2077 flags |= PCM_MMAP | PCM_NOIRQ;
2078 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002079 } else if (out->realtime) {
2080 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002081 } else
2082 flags |= PCM_MONOTONIC;
2083
2084 while (1) {
2085 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2086 flags, &out->config);
2087 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2088 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2089 if (out->pcm != NULL) {
2090 pcm_close(out->pcm);
2091 out->pcm = NULL;
2092 }
2093 if (pcm_open_retry_count-- == 0) {
2094 ret = -EIO;
2095 goto error_open;
2096 }
2097 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2098 continue;
2099 }
2100 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002102
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002103 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2104 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002105
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002106 ALOGV("%s: pcm_prepare", __func__);
2107 if (pcm_is_ready(out->pcm)) {
2108 ret = pcm_prepare(out->pcm);
2109 if (ret < 0) {
2110 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2111 pcm_close(out->pcm);
2112 out->pcm = NULL;
2113 goto error_open;
2114 }
2115 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002117 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2118 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002120 out->compr = compress_open(adev->snd_card,
2121 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002122 COMPRESS_IN, &out->compr_config);
2123 if (out->compr && !is_compress_ready(out->compr)) {
2124 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2125 compress_close(out->compr);
2126 out->compr = NULL;
2127 ret = -EIO;
2128 goto error_open;
2129 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302130 /* compress_open sends params of the track, so reset the flag here */
2131 out->is_compr_metadata_avail = false;
2132
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 if (out->offload_callback)
2134 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002135
Fred Oh3f43e742015-03-04 18:42:34 -08002136 /* Since small bufs uses blocking writes, a write will be blocked
2137 for the default max poll time (20s) in the event of an SSR.
2138 Reduce the poll time to observe and deal with SSR faster.
2139 */
Ashish Jain5106d362016-05-11 19:23:33 +05302140 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002141 compress_set_max_poll_wait(out->compr, 1000);
2142 }
2143
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002144 audio_extn_dts_create_state_notifier_node(out->usecase);
2145 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2146 popcount(out->channel_mask),
2147 out->playback_started);
2148
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002149#ifdef DS1_DOLBY_DDP_ENABLED
2150 if (audio_extn_is_dolby_format(out->format))
2151 audio_extn_dolby_send_ddp_endp_params(adev);
2152#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302153 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002154 if (adev->visualizer_start_output != NULL)
2155 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2156 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302157 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002158 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002161
2162 if (ret == 0) {
2163 register_out_stream(out);
2164 if (out->realtime) {
2165 ret = pcm_start(out->pcm);
2166 if (ret < 0)
2167 goto error_open;
2168 }
2169 }
2170
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302171 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002172 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002173
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002174 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302176 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002178error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302179 /*
2180 * sleep 50ms to allow sufficient time for kernel
2181 * drivers to recover incases like SSR.
2182 */
2183 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002184 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185}
2186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187static int check_input_parameters(uint32_t sample_rate,
2188 audio_format_t format,
2189 int channel_count)
2190{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002191 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302193 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2194 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2195 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002196 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302197 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002198
2199 switch (channel_count) {
2200 case 1:
2201 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302202 case 3:
2203 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002204 case 6:
2205 break;
2206 default:
2207 ret = -EINVAL;
2208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209
2210 switch (sample_rate) {
2211 case 8000:
2212 case 11025:
2213 case 12000:
2214 case 16000:
2215 case 22050:
2216 case 24000:
2217 case 32000:
2218 case 44100:
2219 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302220 case 96000:
2221 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 break;
2223 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002224 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 }
2226
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002227 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228}
2229
2230static size_t get_input_buffer_size(uint32_t sample_rate,
2231 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002232 int channel_count,
2233 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234{
2235 size_t size = 0;
2236
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002237 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2238 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002240 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002241 if (is_low_latency)
2242 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302243
2244 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002246 /* make sure the size is multiple of 32 bytes
2247 * At 48 kHz mono 16-bit PCM:
2248 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2249 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2250 */
2251 size += 0x1f;
2252 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002253
2254 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255}
2256
Ashish Jain5106d362016-05-11 19:23:33 +05302257static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2258{
2259 uint64_t actual_frames_rendered = 0;
2260 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2261
2262 /* This adjustment accounts for buffering after app processor.
2263 * It is based on estimated DSP latency per use case, rather than exact.
2264 */
2265 int64_t platform_latency = platform_render_latency(out->usecase) *
2266 out->sample_rate / 1000000LL;
2267
2268 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2269 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2270 * hence only estimate.
2271 */
2272 int64_t signed_frames = out->written - kernel_buffer_size;
2273
2274 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2275
2276 if (signed_frames > 0)
2277 actual_frames_rendered = signed_frames;
2278
2279 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2280 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2281 (long long int)out->written, (int)kernel_buffer_size,
2282 audio_bytes_per_sample(out->compr_config.codec->format),
2283 popcount(out->channel_mask));
2284
2285 return actual_frames_rendered;
2286}
2287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2289{
2290 struct stream_out *out = (struct stream_out *)stream;
2291
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293}
2294
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002295static int out_set_sample_rate(struct audio_stream *stream __unused,
2296 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297{
2298 return -ENOSYS;
2299}
2300
2301static size_t out_get_buffer_size(const struct audio_stream *stream)
2302{
2303 struct stream_out *out = (struct stream_out *)stream;
2304
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002305 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002306 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002307 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2308 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302309 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302310 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002311
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002312 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002313 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314}
2315
2316static uint32_t out_get_channels(const struct audio_stream *stream)
2317{
2318 struct stream_out *out = (struct stream_out *)stream;
2319
2320 return out->channel_mask;
2321}
2322
2323static audio_format_t out_get_format(const struct audio_stream *stream)
2324{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002325 struct stream_out *out = (struct stream_out *)stream;
2326
2327 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328}
2329
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002330static int out_set_format(struct audio_stream *stream __unused,
2331 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332{
2333 return -ENOSYS;
2334}
2335
2336static int out_standby(struct audio_stream *stream)
2337{
2338 struct stream_out *out = (struct stream_out *)stream;
2339 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002340
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302341 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2342 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002344 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002346 if (adev->adm_deregister_stream)
2347 adev->adm_deregister_stream(adev->adm_data, out->handle);
2348
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002349 if (is_offload_usecase(out->usecase))
2350 stop_compressed_output_l(out);
2351
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002352 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002354 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2355 voice_extn_compress_voip_close_output_stream(stream);
2356 pthread_mutex_unlock(&adev->lock);
2357 pthread_mutex_unlock(&out->lock);
2358 ALOGD("VOIP output entered standby");
2359 return 0;
2360 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 if (out->pcm) {
2362 pcm_close(out->pcm);
2363 out->pcm = NULL;
2364 }
2365 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002366 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302367 out->send_next_track_params = false;
2368 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002369 out->gapless_mdata.encoder_delay = 0;
2370 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 if (out->compr != NULL) {
2372 compress_close(out->compr);
2373 out->compr = NULL;
2374 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002375 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002377 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 }
2379 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302380 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 return 0;
2382}
2383
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002384static int out_dump(const struct audio_stream *stream __unused,
2385 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386{
2387 return 0;
2388}
2389
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002390static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2391{
2392 int ret = 0;
2393 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002394
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002395 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002396 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002397 return -EINVAL;
2398 }
2399
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302400 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002401
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002402 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2403 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302404 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002405 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002406 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2407 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302408 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002409 }
2410
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002411 ALOGV("%s new encoder delay %u and padding %u", __func__,
2412 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2413
2414 return 0;
2415}
2416
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002417static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2418{
2419 return out == adev->primary_output || out == adev->voice_tx_output;
2420}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2423{
2424 struct stream_out *out = (struct stream_out *)stream;
2425 struct audio_device *adev = out->dev;
2426 struct str_parms *parms;
2427 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002428 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429
sangwoobc677242013-08-08 16:53:43 +09002430 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002431 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302433 if (!parms)
2434 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002435 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2436 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002438 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002439 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002441 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002442 * When HDMI cable is unplugged the music playback is paused and
2443 * the policy manager sends routing=0. But the audioflinger continues
2444 * to write data until standby time (3sec). As the HDMI core is
2445 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002446 * Avoid this by routing audio to speaker until standby.
2447 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002448 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2449 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302450 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002451 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2452 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002453 }
2454
2455 /*
2456 * select_devices() call below switches all the usecases on the same
2457 * backend to the new device. Refer to check_usecases_codec_backend() in
2458 * the select_devices(). But how do we undo this?
2459 *
2460 * For example, music playback is active on headset (deep-buffer usecase)
2461 * and if we go to ringtones and select a ringtone, low-latency usecase
2462 * will be started on headset+speaker. As we can't enable headset+speaker
2463 * and headset devices at the same time, select_devices() switches the music
2464 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2465 * So when the ringtone playback is completed, how do we undo the same?
2466 *
2467 * We are relying on the out_set_parameters() call on deep-buffer output,
2468 * once the ringtone playback is ended.
2469 * NOTE: We should not check if the current devices are same as new devices.
2470 * Because select_devices() must be called to switch back the music
2471 * playback to headset.
2472 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002473 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002474 audio_devices_t new_dev = val;
2475 bool same_dev = out->devices == new_dev;
2476 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002477
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002478 if (output_drives_call(adev, out)) {
2479 if(!voice_is_in_call(adev)) {
2480 if (adev->mode == AUDIO_MODE_IN_CALL) {
2481 adev->current_call_output = out;
2482 ret = voice_start_call(adev);
2483 }
2484 } else {
2485 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002486 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002487 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002488 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002489
2490 if (!out->standby) {
2491 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2492 adev->perf_lock_opts,
2493 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002494 if (!same_dev) {
2495 ALOGV("update routing change");
2496 out->routing_change = true;
2497 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002498 select_devices(adev, out->usecase);
2499 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2500 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002501 }
2502
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002504 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002506
2507 if (out == adev->primary_output) {
2508 pthread_mutex_lock(&adev->lock);
2509 audio_extn_set_parameters(adev, parms);
2510 pthread_mutex_unlock(&adev->lock);
2511 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002512 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002513 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002514 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002515
2516 audio_extn_dts_create_state_notifier_node(out->usecase);
2517 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2518 popcount(out->channel_mask),
2519 out->playback_started);
2520
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002521 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002522 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302525error:
Eric Laurent994a6932013-07-17 11:51:42 -07002526 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 return ret;
2528}
2529
2530static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2531{
2532 struct stream_out *out = (struct stream_out *)stream;
2533 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002534 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 char value[256];
2536 struct str_parms *reply = str_parms_create();
2537 size_t i, j;
2538 int ret;
2539 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002540
2541 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002542 if (reply) {
2543 str_parms_destroy(reply);
2544 }
2545 if (query) {
2546 str_parms_destroy(query);
2547 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002548 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2549 return NULL;
2550 }
2551
Eric Laurent994a6932013-07-17 11:51:42 -07002552 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2554 if (ret >= 0) {
2555 value[0] = '\0';
2556 i = 0;
2557 while (out->supported_channel_masks[i] != 0) {
2558 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2559 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2560 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002561 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002563 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 first = false;
2565 break;
2566 }
2567 }
2568 i++;
2569 }
2570 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2571 str = str_parms_to_str(reply);
2572 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002573 voice_extn_out_get_parameters(out, query, reply);
2574 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002575 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002576 free(str);
2577 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002578 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002580
Alexy Joseph62142aa2015-11-16 15:10:34 -08002581
2582 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2583 if (ret >= 0) {
2584 value[0] = '\0';
2585 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2586 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302587 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002588 } else {
2589 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302590 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002591 }
2592 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002593 if (str)
2594 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002595 str = str_parms_to_str(reply);
2596 }
2597
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002598 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2599 if (ret >= 0) {
2600 value[0] = '\0';
2601 i = 0;
2602 first = true;
2603 while (out->supported_formats[i] != 0) {
2604 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2605 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2606 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002607 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002608 }
2609 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2610 first = false;
2611 break;
2612 }
2613 }
2614 i++;
2615 }
2616 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002617 if (str)
2618 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002619 str = str_parms_to_str(reply);
2620 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002621
2622 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2623 if (ret >= 0) {
2624 value[0] = '\0';
2625 i = 0;
2626 first = true;
2627 while (out->supported_sample_rates[i] != 0) {
2628 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2629 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2630 if (!first) {
2631 strlcat(value, "|", sizeof(value));
2632 }
2633 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2634 first = false;
2635 break;
2636 }
2637 }
2638 i++;
2639 }
2640 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2641 if (str)
2642 free(str);
2643 str = str_parms_to_str(reply);
2644 }
2645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 str_parms_destroy(query);
2647 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002648 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 return str;
2650}
2651
2652static uint32_t out_get_latency(const struct audio_stream_out *stream)
2653{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002654 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002656 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657
Alexy Josephaa54c872014-12-03 02:46:47 -08002658 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002659 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002660 } else if (out->realtime) {
2661 // since the buffer won't be filled up faster than realtime,
2662 // return a smaller number
2663 if (out->config.rate)
2664 period_ms = (out->af_period_multiplier * out->config.period_size *
2665 1000) / (out->config.rate);
2666 else
2667 period_ms = 0;
2668 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002669 } else {
2670 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002671 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002672 }
2673
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302674 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002675 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676}
2677
2678static int out_set_volume(struct audio_stream_out *stream, float left,
2679 float right)
2680{
Eric Laurenta9024de2013-04-04 09:19:12 -07002681 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002682 int volume[2];
2683
Eric Laurenta9024de2013-04-04 09:19:12 -07002684 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2685 /* only take left channel into account: the API is for stereo anyway */
2686 out->muted = (left == 0.0f);
2687 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002688 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302689 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002690 /*
2691 * Set mute or umute on HDMI passthrough stream.
2692 * Only take left channel into account.
2693 * Mute is 0 and unmute 1
2694 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302695 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002696 } else {
2697 char mixer_ctl_name[128];
2698 struct audio_device *adev = out->dev;
2699 struct mixer_ctl *ctl;
2700 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002701 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002702
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002703 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2704 "Compress Playback %d Volume", pcm_device_id);
2705 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2706 if (!ctl) {
2707 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2708 __func__, mixer_ctl_name);
2709 return -EINVAL;
2710 }
2711 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2712 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2713 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2714 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002716 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 return -ENOSYS;
2719}
2720
2721static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2722 size_t bytes)
2723{
2724 struct stream_out *out = (struct stream_out *)stream;
2725 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302726 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002727 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002729 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302730
Naresh Tanniru80659832014-06-04 18:17:56 +05302731 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002732
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302733 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302734 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302735 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2736 pthread_mutex_unlock(&out->lock);
2737 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302738 } else {
2739 /* increase written size during SSR to avoid mismatch
2740 * with the written frames count in AF
2741 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302742 if (audio_bytes_per_sample(out->format) != 0)
2743 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302744 ALOGD(" %s: sound card is not active/SSR state", __func__);
2745 ret= -EIO;
2746 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302747 }
2748 }
2749
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302750 if (audio_extn_passthru_should_drop_data(out)) {
2751 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2752 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2753 out_get_sample_rate(&out->stream.common));
2754 goto exit;
2755 }
2756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002758 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002759 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002760 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2761 ret = voice_extn_compress_voip_start_output_stream(out);
2762 else
2763 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002764 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002767 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 goto exit;
2769 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002770
2771 if (last_known_cal_step != -1) {
2772 ALOGD("%s: retry previous failed cal level set", __func__);
2773 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2774 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776
Ashish Jain81eb2a82015-05-13 10:52:34 +05302777 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002778 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302779 adev->is_channel_status_set = true;
2780 }
2781
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002782 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002783 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002784 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002785 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002786 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2787 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302788 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2789 ALOGD("copl(%p):send next track params in gapless", out);
2790 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2791 out->send_next_track_params = false;
2792 out->is_compr_metadata_avail = false;
2793 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002794 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302795 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302796 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002797
Ashish Jain83a6cc22016-06-28 14:34:17 +05302798 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302799 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302800 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302801 pthread_mutex_unlock(&out->lock);
2802 return -EINVAL;
2803 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302804 audio_format_t dst_format = out->hal_op_format;
2805 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302806
2807 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2808 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2809
Ashish Jain83a6cc22016-06-28 14:34:17 +05302810 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302811 dst_format,
2812 buffer,
2813 src_format,
2814 frames);
2815
Ashish Jain83a6cc22016-06-28 14:34:17 +05302816 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302817 bytes_to_write);
2818
2819 /*Convert written bytes in audio flinger format*/
2820 if (ret > 0)
2821 ret = ((ret * format_to_bitwidth_table[out->format]) /
2822 format_to_bitwidth_table[dst_format]);
2823 }
2824 } else
2825 ret = compress_write(out->compr, buffer, bytes);
2826
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302827 if (ret < 0)
2828 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302829 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002830 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302831 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302833 } else if (-ENETRESET == ret) {
2834 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2835 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2836 pthread_mutex_unlock(&out->lock);
2837 out_standby(&out->stream.common);
2838 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002839 }
Ashish Jain5106d362016-05-11 19:23:33 +05302840 if ( ret == (ssize_t)bytes && !out->non_blocking)
2841 out->written += bytes;
2842
Naresh Tanniru80659832014-06-04 18:17:56 +05302843 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002845 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 out->playback_started = 1;
2847 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002848
2849 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2850 popcount(out->channel_mask),
2851 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852 }
2853 pthread_mutex_unlock(&out->lock);
2854 return ret;
2855 } else {
2856 if (out->pcm) {
2857 if (out->muted)
2858 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002859
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302860 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002861
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002862 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002863
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002864 if (out->config.rate)
2865 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2866 out->config.rate;
2867
2868 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2869
2870 request_out_focus(out, ns);
2871
2872 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002873 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002874 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302875 out->convert_buffer != NULL) {
2876
2877 memcpy_by_audio_format(out->convert_buffer,
2878 out->hal_op_format,
2879 buffer,
2880 out->hal_ip_format,
2881 out->config.period_size * out->config.channels);
2882
2883 ret = pcm_write(out->pcm, out->convert_buffer,
2884 (out->config.period_size *
2885 out->config.channels *
2886 format_to_bitwidth_table[out->hal_op_format]));
2887 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002888 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302889 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002890
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002891 release_out_focus(out);
2892
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302893 if (ret < 0)
2894 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302895 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2896 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2897 else
2898 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 }
2901
2902exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302903 /* ToDo: There may be a corner case when SSR happens back to back during
2904 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302905 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302906 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302907 }
2908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 pthread_mutex_unlock(&out->lock);
2910
2911 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002912 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002913 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302914 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302915 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302916 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302917 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302918 out->standby = true;
2919 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302921 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302922 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923 }
2924 return bytes;
2925}
2926
2927static int out_get_render_position(const struct audio_stream_out *stream,
2928 uint32_t *dsp_frames)
2929{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302931 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002932
2933 if (dsp_frames == NULL)
2934 return -EINVAL;
2935
2936 *dsp_frames = 0;
2937 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002938 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302939
2940 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2941 * this operation and adev_close_output_stream(where out gets reset).
2942 */
2943 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2944 *dsp_frames = get_actual_pcm_frames_rendered(out);
2945 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2946 return 0;
2947 }
2948
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002949 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302950 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302951 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302953 if (ret < 0)
2954 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302956 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 }
2958 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302959 if (-ENETRESET == ret) {
2960 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2961 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2962 return -EINVAL;
2963 } else if(ret < 0) {
2964 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2965 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302966 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2967 /*
2968 * Handle corner case where compress session is closed during SSR
2969 * and timestamp is queried
2970 */
2971 ALOGE(" ERROR: sound card not active, return error");
2972 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302973 } else {
2974 return 0;
2975 }
Zhou Song32a556e2015-05-05 10:46:56 +08002976 } else if (audio_is_linear_pcm(out->format)) {
2977 *dsp_frames = out->written;
2978 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002979 } else
2980 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981}
2982
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002983static int out_add_audio_effect(const struct audio_stream *stream __unused,
2984 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985{
2986 return 0;
2987}
2988
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002989static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2990 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991{
2992 return 0;
2993}
2994
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002995static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2996 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997{
2998 return -EINVAL;
2999}
3000
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003001static int out_get_presentation_position(const struct audio_stream_out *stream,
3002 uint64_t *frames, struct timespec *timestamp)
3003{
3004 struct stream_out *out = (struct stream_out *)stream;
3005 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003006 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003007
Ashish Jain5106d362016-05-11 19:23:33 +05303008 /* below piece of code is not guarded against any lock because audioFliner serializes
3009 * this operation and adev_close_output_stream( where out gets reset).
3010 */
3011 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3012 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3013 *frames = get_actual_pcm_frames_rendered(out);
3014 /* this is the best we can do */
3015 clock_gettime(CLOCK_MONOTONIC, timestamp);
3016 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3017 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3018 return 0;
3019 }
3020
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003021 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003022
Ashish Jain5106d362016-05-11 19:23:33 +05303023 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3024 ret = compress_get_tstamp(out->compr, &dsp_frames,
3025 &out->sample_rate);
3026 ALOGVV("%s rendered frames %ld sample_rate %d",
3027 __func__, dsp_frames, out->sample_rate);
3028 *frames = dsp_frames;
3029 if (ret < 0)
3030 ret = -errno;
3031 if (-ENETRESET == ret) {
3032 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3033 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3034 ret = -EINVAL;
3035 } else
3036 ret = 0;
3037 /* this is the best we can do */
3038 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003039 } else {
3040 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003041 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003042 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3043 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003044 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003045 // This adjustment accounts for buffering after app processor.
3046 // It is based on estimated DSP latency per use case, rather than exact.
3047 signed_frames -=
3048 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3049
Eric Laurent949a0892013-09-20 09:20:13 -07003050 // It would be unusual for this value to be negative, but check just in case ...
3051 if (signed_frames >= 0) {
3052 *frames = signed_frames;
3053 ret = 0;
3054 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003055 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303056 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3057 *frames = out->written;
3058 clock_gettime(CLOCK_MONOTONIC, timestamp);
3059 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003060 }
3061 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003062 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003063 return ret;
3064}
3065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066static int out_set_callback(struct audio_stream_out *stream,
3067 stream_callback_t callback, void *cookie)
3068{
3069 struct stream_out *out = (struct stream_out *)stream;
3070
3071 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003072 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 out->offload_callback = callback;
3074 out->offload_cookie = cookie;
3075 pthread_mutex_unlock(&out->lock);
3076 return 0;
3077}
3078
3079static int out_pause(struct audio_stream_out* stream)
3080{
3081 struct stream_out *out = (struct stream_out *)stream;
3082 int status = -ENOSYS;
3083 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003084 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003085 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003086 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303088 struct audio_device *adev = out->dev;
3089 int snd_scard_state = get_snd_card_state(adev);
3090
3091 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3092 status = compress_pause(out->compr);
3093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003095
Mingming Yin21854652016-04-13 11:54:02 -07003096 if (audio_extn_passthru_is_active()) {
3097 ALOGV("offload use case, pause passthru");
3098 audio_extn_passthru_on_pause(out);
3099 }
3100
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303101 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003102 audio_extn_dts_notify_playback_state(out->usecase, 0,
3103 out->sample_rate, popcount(out->channel_mask),
3104 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 }
3106 pthread_mutex_unlock(&out->lock);
3107 }
3108 return status;
3109}
3110
3111static int out_resume(struct audio_stream_out* stream)
3112{
3113 struct stream_out *out = (struct stream_out *)stream;
3114 int status = -ENOSYS;
3115 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003116 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003117 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003118 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003119 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303121 struct audio_device *adev = out->dev;
3122 int snd_scard_state = get_snd_card_state(adev);
3123
Mingming Yin21854652016-04-13 11:54:02 -07003124 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3125 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3126 pthread_mutex_lock(&out->dev->lock);
3127 ALOGV("offload resume, check and set hdmi backend again");
3128 check_and_set_hdmi_backend(out);
3129 pthread_mutex_unlock(&out->dev->lock);
3130 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303131 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003132 }
3133 if (!status) {
3134 out->offload_state = OFFLOAD_STATE_PLAYING;
3135 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303136 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003137 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3138 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 }
3140 pthread_mutex_unlock(&out->lock);
3141 }
3142 return status;
3143}
3144
3145static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3146{
3147 struct stream_out *out = (struct stream_out *)stream;
3148 int status = -ENOSYS;
3149 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003150 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003151 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003152 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3153 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3154 else
3155 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3156 pthread_mutex_unlock(&out->lock);
3157 }
3158 return status;
3159}
3160
3161static int out_flush(struct audio_stream_out* stream)
3162{
3163 struct stream_out *out = (struct stream_out *)stream;
3164 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003165 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003166 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003167 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003168 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303169 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003170 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003171 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003172 return 0;
3173 }
3174 return -ENOSYS;
3175}
3176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177/** audio_stream_in implementation **/
3178static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3179{
3180 struct stream_in *in = (struct stream_in *)stream;
3181
3182 return in->config.rate;
3183}
3184
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003185static int in_set_sample_rate(struct audio_stream *stream __unused,
3186 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187{
3188 return -ENOSYS;
3189}
3190
3191static size_t in_get_buffer_size(const struct audio_stream *stream)
3192{
3193 struct stream_in *in = (struct stream_in *)stream;
3194
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003195 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3196 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003197 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3198 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003199
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003200 return in->config.period_size * in->af_period_multiplier *
3201 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202}
3203
3204static uint32_t in_get_channels(const struct audio_stream *stream)
3205{
3206 struct stream_in *in = (struct stream_in *)stream;
3207
3208 return in->channel_mask;
3209}
3210
3211static audio_format_t in_get_format(const struct audio_stream *stream)
3212{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003213 struct stream_in *in = (struct stream_in *)stream;
3214
3215 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216}
3217
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003218static int in_set_format(struct audio_stream *stream __unused,
3219 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220{
3221 return -ENOSYS;
3222}
3223
3224static int in_standby(struct audio_stream *stream)
3225{
3226 struct stream_in *in = (struct stream_in *)stream;
3227 struct audio_device *adev = in->dev;
3228 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303229 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3230 stream, in->usecase, use_case_table[in->usecase]);
3231
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003232 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003233 if (!in->standby && in->is_st_session) {
3234 ALOGD("%s: sound trigger pcm stop lab", __func__);
3235 audio_extn_sound_trigger_stop_lab(in);
3236 in->standby = 1;
3237 }
3238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003240 if (adev->adm_deregister_stream)
3241 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3242
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003243 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003245 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3246 voice_extn_compress_voip_close_input_stream(stream);
3247 ALOGD("VOIP input entered standby");
3248 } else {
3249 if (in->pcm) {
3250 pcm_close(in->pcm);
3251 in->pcm = NULL;
3252 }
3253 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003254 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003255 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 }
3257 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003258 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 return status;
3260}
3261
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003262static int in_dump(const struct audio_stream *stream __unused,
3263 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264{
3265 return 0;
3266}
3267
3268static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3269{
3270 struct stream_in *in = (struct stream_in *)stream;
3271 struct audio_device *adev = in->dev;
3272 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003274 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303276 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277 parms = str_parms_create_str(kvpairs);
3278
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303279 if (!parms)
3280 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003281 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003282 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003283
3284 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3285 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 val = atoi(value);
3287 /* no audio source uses val == 0 */
3288 if ((in->source != val) && (val != 0)) {
3289 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003290 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3291 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3292 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003293 (in->config.rate == 8000 || in->config.rate == 16000 ||
3294 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003295 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003296 err = voice_extn_compress_voip_open_input_stream(in);
3297 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003298 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003299 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003300 }
3301 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 }
3303 }
3304
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003305 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3306 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003308 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 in->device = val;
3310 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003311 if (!in->standby && !in->is_st_session) {
3312 ALOGV("update input routing change");
3313 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003314 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 }
3317 }
3318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003320 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321
3322 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303323error:
Eric Laurent994a6932013-07-17 11:51:42 -07003324 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 return ret;
3326}
3327
3328static char* in_get_parameters(const struct audio_stream *stream,
3329 const char *keys)
3330{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003331 struct stream_in *in = (struct stream_in *)stream;
3332 struct str_parms *query = str_parms_create_str(keys);
3333 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003334 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003335
3336 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003337 if (reply) {
3338 str_parms_destroy(reply);
3339 }
3340 if (query) {
3341 str_parms_destroy(query);
3342 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003343 ALOGE("in_get_parameters: failed to create query or reply");
3344 return NULL;
3345 }
3346
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003347 ALOGV("%s: enter: keys - %s", __func__, keys);
3348
3349 voice_extn_in_get_parameters(in, query, reply);
3350
3351 str = str_parms_to_str(reply);
3352 str_parms_destroy(query);
3353 str_parms_destroy(reply);
3354
3355 ALOGV("%s: exit: returns - %s", __func__, str);
3356 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357}
3358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003359static int in_set_gain(struct audio_stream_in *stream __unused,
3360 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361{
3362 return 0;
3363}
3364
3365static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3366 size_t bytes)
3367{
3368 struct stream_in *in = (struct stream_in *)stream;
3369 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303370 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303371 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303372 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003374 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303375
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003376 if (in->is_st_session) {
3377 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3378 /* Read from sound trigger HAL */
3379 audio_extn_sound_trigger_read(in, buffer, bytes);
3380 pthread_mutex_unlock(&in->lock);
3381 return bytes;
3382 }
3383
Ashish Jainbbce4322016-02-16 13:25:27 +05303384 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003385 ALOGD(" %s: sound card is not active/SSR state", __func__);
3386 ret= -EIO;;
3387 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303388 }
3389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003391 pthread_mutex_lock(&adev->lock);
3392 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3393 ret = voice_extn_compress_voip_start_input_stream(in);
3394 else
3395 ret = start_input_stream(in);
3396 pthread_mutex_unlock(&adev->lock);
3397 if (ret != 0) {
3398 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399 }
3400 in->standby = 0;
3401 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003403 // what's the duration requested by the client?
3404 long ns = 0;
3405
3406 if (in->config.rate)
3407 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3408 in->config.rate;
3409
3410 request_in_focus(in, ns);
3411 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003413 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303414 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003415 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303416 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003417 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003418 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003419 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303420 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003421 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303422 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3423 if (bytes % 4 == 0) {
3424 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3425 int_buf_stream = buffer;
3426 for (size_t itt=0; itt < bytes/4 ; itt++) {
3427 int_buf_stream[itt] >>= 8;
3428 }
3429 } else {
3430 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3431 ret = -EINVAL;
3432 goto exit;
3433 }
3434 } if (ret < 0) {
3435 ret = -errno;
3436 }
3437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 }
3439
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003440 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 /*
3443 * Instead of writing zeroes here, we could trust the hardware
3444 * to always provide zeroes when muted.
3445 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303446 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3447 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 memset(buffer, 0, bytes);
3449
3450exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303451 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303452 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003453 if (-ENETRESET == ret)
3454 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 pthread_mutex_unlock(&in->lock);
3457
3458 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303459 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303460 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303461 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303462 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303463 in->standby = true;
3464 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303465 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003467 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303468 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303469 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003470 }
3471 return bytes;
3472}
3473
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003474static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475{
3476 return 0;
3477}
3478
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003479static int add_remove_audio_effect(const struct audio_stream *stream,
3480 effect_handle_t effect,
3481 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003483 struct stream_in *in = (struct stream_in *)stream;
3484 int status = 0;
3485 effect_descriptor_t desc;
3486
3487 status = (*effect)->get_descriptor(effect, &desc);
3488 if (status != 0)
3489 return status;
3490
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003491 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003492 pthread_mutex_lock(&in->dev->lock);
3493 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3494 in->enable_aec != enable &&
3495 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3496 in->enable_aec = enable;
3497 if (!in->standby)
3498 select_devices(in->dev, in->usecase);
3499 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003500 if (in->enable_ns != enable &&
3501 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3502 in->enable_ns = enable;
3503 if (!in->standby)
3504 select_devices(in->dev, in->usecase);
3505 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003506 pthread_mutex_unlock(&in->dev->lock);
3507 pthread_mutex_unlock(&in->lock);
3508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 return 0;
3510}
3511
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003512static int in_add_audio_effect(const struct audio_stream *stream,
3513 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514{
Eric Laurent994a6932013-07-17 11:51:42 -07003515 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003516 return add_remove_audio_effect(stream, effect, true);
3517}
3518
3519static int in_remove_audio_effect(const struct audio_stream *stream,
3520 effect_handle_t effect)
3521{
Eric Laurent994a6932013-07-17 11:51:42 -07003522 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003523 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524}
3525
3526static int adev_open_output_stream(struct audio_hw_device *dev,
3527 audio_io_handle_t handle,
3528 audio_devices_t devices,
3529 audio_output_flags_t flags,
3530 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003531 struct audio_stream_out **stream_out,
3532 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533{
3534 struct audio_device *adev = (struct audio_device *)dev;
3535 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303536 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003537 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303540
3541 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3542 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003543 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303544 return -EINVAL;
3545 }
3546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3548
Mingming Yin3a941d42016-02-17 18:08:05 -08003549 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3550 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303551 devices, flags, &out->stream);
3552
3553
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003554 if (!out) {
3555 return -ENOMEM;
3556 }
3557
Haynes Mathew George204045b2015-02-25 20:32:03 -08003558 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003559 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003560 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 if (devices == AUDIO_DEVICE_NONE)
3563 devices = AUDIO_DEVICE_OUT_SPEAKER;
3564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 out->flags = flags;
3566 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003567 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003568 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003569 out->sample_rate = config->sample_rate;
3570 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3571 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003572 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003573 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003574 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303575 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576
Mingming Yin3a941d42016-02-17 18:08:05 -08003577 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3578 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3579 pthread_mutex_lock(&adev->lock);
3580 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3581 ret = read_hdmi_sink_caps(out);
3582 pthread_mutex_unlock(&adev->lock);
3583 if (ret != 0) {
3584 if (ret == -ENOSYS) {
3585 /* ignore and go with default */
3586 ret = 0;
3587 } else {
3588 ALOGE("error reading hdmi sink caps");
3589 goto error_open;
3590 }
3591 }
3592 }
3593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003595 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303596 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3597 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003598 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3599 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3600
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003601 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003602 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3603 /*
3604 * Do not handle stereo output in Multi-channel cases
3605 * Stereo case is handled in normal playback path
3606 */
3607 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3608 ret = AUDIO_CHANNEL_OUT_STEREO;
3609 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003610
3611 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3612 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003613 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003614 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003615 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003616
3617 if (config->sample_rate == 0)
3618 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3619 if (config->channel_mask == 0)
3620 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003621 if (config->format == 0)
3622 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003623
3624 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003625 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003626 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3628 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003630 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003632 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3633 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003634 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003635 ret = voice_extn_compress_voip_open_output_stream(out);
3636 if (ret != 0) {
3637 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3638 __func__, ret);
3639 goto error_open;
3640 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003641 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3642 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003644 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3645 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3646 ALOGE("%s: Unsupported Offload information", __func__);
3647 ret = -EINVAL;
3648 goto error_open;
3649 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003650
Mingming Yin3a941d42016-02-17 18:08:05 -08003651 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003652 if(config->offload_info.format == 0)
3653 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003654 if (config->offload_info.sample_rate == 0)
3655 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003656 }
3657
Mingming Yin90310102013-11-13 16:57:00 -08003658 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303659 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003660 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003661 ret = -EINVAL;
3662 goto error_open;
3663 }
3664
3665 out->compr_config.codec = (struct snd_codec *)
3666 calloc(1, sizeof(struct snd_codec));
3667
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003668 if (!out->compr_config.codec) {
3669 ret = -ENOMEM;
3670 goto error_open;
3671 }
3672
vivek mehta0ea887a2015-08-26 14:01:20 -07003673 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303674 out->stream.pause = out_pause;
3675 out->stream.flush = out_flush;
3676 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003677 out->usecase = get_offload_usecase(adev, true);
3678 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003679 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003680 out->stream.set_callback = out_set_callback;
3681 out->stream.pause = out_pause;
3682 out->stream.resume = out_resume;
3683 out->stream.drain = out_drain;
3684 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003685 out->usecase = get_offload_usecase(adev, false);
3686 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003687 }
vivek mehta446c3962015-09-14 10:57:35 -07003688
3689 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003690 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3691 config->format == 0 && config->sample_rate == 0 &&
3692 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003693 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003694 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3695 } else {
3696 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3697 ret = -EEXIST;
3698 goto error_open;
3699 }
vivek mehta446c3962015-09-14 10:57:35 -07003700 }
3701
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003702 if (config->offload_info.channel_mask)
3703 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003704 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003705 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003706 config->offload_info.channel_mask = config->channel_mask;
3707 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003708 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003709 out->sample_rate = config->offload_info.sample_rate;
3710
Mingming Yin3ee55c62014-08-04 14:23:35 -07003711 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303713 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3714 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3715 audio_extn_dolby_send_ddp_endp_params(adev);
3716 audio_extn_dolby_set_dmid(adev);
3717 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003718
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003719 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003720 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003721 out->compr_config.codec->bit_rate =
3722 config->offload_info.bit_rate;
3723 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003724 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003725 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303726 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003727 /*TODO: Do we need to change it for passthrough */
3728 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003729
Manish Dewangana6fc5442015-08-24 20:30:31 +05303730 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3731 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3732 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3733 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303734
3735 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3736 AUDIO_FORMAT_PCM) {
3737
3738 /*Based on platform support, configure appropriate alsa format for corresponding
3739 *hal input format.
3740 */
3741 out->compr_config.codec->format = hal_format_to_alsa(
3742 config->offload_info.format);
3743
Ashish Jain83a6cc22016-06-28 14:34:17 +05303744 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303745 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303746 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303747
3748 /*for direct PCM playback populate bit_width based on selected alsa format as
3749 *hal input format and alsa format might differ based on platform support.
3750 */
3751 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303752 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303753
3754 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3755
3756 /* Check if alsa session is configured with the same format as HAL input format,
3757 * if not then derive correct fragment size needed to accomodate the
3758 * conversion of HAL input format to alsa format.
3759 */
3760 audio_extn_utils_update_direct_pcm_fragment_size(out);
3761
3762 /*if hal input and output fragment size is different this indicates HAL input format is
3763 *not same as the alsa format
3764 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303765 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303766 /*Allocate a buffer to convert input data to the alsa configured format.
3767 *size of convert buffer is equal to the size required to hold one fragment size
3768 *worth of pcm data, this is because flinger does not write more than fragment_size
3769 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303770 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3771 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303772 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3773 ret = -ENOMEM;
3774 goto error_open;
3775 }
3776 }
3777 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3778 out->compr_config.fragment_size =
3779 audio_extn_passthru_get_buffer_size(&config->offload_info);
3780 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3781 } else {
3782 out->compr_config.fragment_size =
3783 platform_get_compress_offload_buffer_size(&config->offload_info);
3784 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3785 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003786
Amit Shekhar6f461b12014-08-01 14:52:58 -07003787 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303788 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003789
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003790 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3791 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003792
Alexy Josephaa54c872014-12-03 02:46:47 -08003793
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003794 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303795 out->send_next_track_params = false;
3796 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003797 out->offload_state = OFFLOAD_STATE_IDLE;
3798 out->playback_started = 0;
3799
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003800 audio_extn_dts_create_state_notifier_node(out->usecase);
3801
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003802 create_offload_callback_thread(out);
3803 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3804 __func__, config->offload_info.version,
3805 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303806
3807 /* Disable gapless if any of the following is true
3808 * passthrough playback
3809 * AV playback
3810 * Direct PCM playback
3811 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303812 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303813 config->offload_info.has_video ||
3814 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3815 check_and_set_gapless_mode(adev, false);
3816 } else
3817 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003818
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303819 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003820 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3821 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003822 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303823 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003824 if (ret != 0) {
3825 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3826 __func__, ret);
3827 goto error_open;
3828 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003829 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3830 if (config->sample_rate == 0)
3831 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3832 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3833 config->sample_rate != 8000) {
3834 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3835 ret = -EINVAL;
3836 goto error_open;
3837 }
3838 out->sample_rate = config->sample_rate;
3839 out->config.rate = config->sample_rate;
3840 if (config->format == AUDIO_FORMAT_DEFAULT)
3841 config->format = AUDIO_FORMAT_PCM_16_BIT;
3842 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3843 config->format = AUDIO_FORMAT_PCM_16_BIT;
3844 ret = -EINVAL;
3845 goto error_open;
3846 }
3847 out->format = config->format;
3848 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3849 out->config = pcm_config_afe_proxy_playback;
3850 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003851 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303852 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3853 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003854 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3855 out->flags);
3856 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303857 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3858 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3859 out->config = pcm_config_low_latency;
3860 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3861 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3862 out->config = pcm_config_deep_buffer;
3863 } else {
3864 /* primary path is the default path selected if no other outputs are available/suitable */
3865 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3866 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3867 }
3868 out->hal_ip_format = format = out->format;
3869 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3870 out->hal_op_format = pcm_format_to_hal(out->config.format);
3871 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3872 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003873 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303874 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3875 if (out->hal_ip_format != out->hal_op_format) {
3876 uint32_t buffer_size = out->config.period_size *
3877 format_to_bitwidth_table[out->hal_op_format] *
3878 out->config.channels;
3879 out->convert_buffer = calloc(1, buffer_size);
3880 if (out->convert_buffer == NULL){
3881 ALOGE("Allocation failed for convert buffer for size %d",
3882 out->compr_config.fragment_size);
3883 ret = -ENOMEM;
3884 goto error_open;
3885 }
3886 ALOGD("Convert buffer allocated of size %d", buffer_size);
3887 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 }
3889
Ashish Jain83a6cc22016-06-28 14:34:17 +05303890 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3891 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3892
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003893 /* TODO remove this hardcoding and check why width is zero*/
3894 if (out->bit_width == 0)
3895 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003896 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3897 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003898 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303899 out->bit_width, out->channel_mask,
3900 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003901 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3902 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3903 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003904 if(adev->primary_output == NULL)
3905 adev->primary_output = out;
3906 else {
3907 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003908 ret = -EEXIST;
3909 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003910 }
3911 }
3912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 /* Check if this usecase is already existing */
3914 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003915 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3916 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003919 ret = -EEXIST;
3920 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921 }
3922 pthread_mutex_unlock(&adev->lock);
3923
3924 out->stream.common.get_sample_rate = out_get_sample_rate;
3925 out->stream.common.set_sample_rate = out_set_sample_rate;
3926 out->stream.common.get_buffer_size = out_get_buffer_size;
3927 out->stream.common.get_channels = out_get_channels;
3928 out->stream.common.get_format = out_get_format;
3929 out->stream.common.set_format = out_set_format;
3930 out->stream.common.standby = out_standby;
3931 out->stream.common.dump = out_dump;
3932 out->stream.common.set_parameters = out_set_parameters;
3933 out->stream.common.get_parameters = out_get_parameters;
3934 out->stream.common.add_audio_effect = out_add_audio_effect;
3935 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3936 out->stream.get_latency = out_get_latency;
3937 out->stream.set_volume = out_set_volume;
3938 out->stream.write = out_write;
3939 out->stream.get_render_position = out_get_render_position;
3940 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003941 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003943 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003945 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003946 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947
3948 config->format = out->stream.common.get_format(&out->stream.common);
3949 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3950 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3951
3952 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303953 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003954 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003955
3956 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3957 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3958 popcount(out->channel_mask), out->playback_started);
3959
Eric Laurent994a6932013-07-17 11:51:42 -07003960 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003962
3963error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303964 if (out->convert_buffer)
3965 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003966 free(out);
3967 *stream_out = NULL;
3968 ALOGD("%s: exit: ret %d", __func__, ret);
3969 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970}
3971
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003972static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973 struct audio_stream_out *stream)
3974{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975 struct stream_out *out = (struct stream_out *)stream;
3976 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003977 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003978
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303979 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3980
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003981 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303982 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003983 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303984 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003985 if(ret != 0)
3986 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3987 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003988 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003989 out_standby(&stream->common);
3990
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003991 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003992 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003993 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003994 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 if (out->compr_config.codec != NULL)
3996 free(out->compr_config.codec);
3997 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003998
Ashish Jain83a6cc22016-06-28 14:34:17 +05303999 if (out->convert_buffer != NULL) {
4000 free(out->convert_buffer);
4001 out->convert_buffer = NULL;
4002 }
4003
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004004 if (adev->voice_tx_output == out)
4005 adev->voice_tx_output = NULL;
4006
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004007 pthread_cond_destroy(&out->cond);
4008 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004010 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011}
4012
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004013static void close_compress_sessions(struct audio_device *adev)
4014{
Mingming Yin7b762e72015-03-04 13:47:32 -08004015 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304016 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004017 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004018 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304019
4020 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004021 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304022 if (is_offload_usecase(usecase->id)) {
4023 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004024 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4025 out = usecase->stream.out;
4026 pthread_mutex_unlock(&adev->lock);
4027 out_standby(&out->stream.common);
4028 pthread_mutex_lock(&adev->lock);
4029 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304030 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004031 }
4032 pthread_mutex_unlock(&adev->lock);
4033}
4034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4036{
4037 struct audio_device *adev = (struct audio_device *)dev;
4038 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004040 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004041 int ret;
4042 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004044 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304047 if (!parms)
4048 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004049 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4050 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304051 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304052 if (strstr(snd_card_status, "OFFLINE")) {
4053 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304054 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004055 //close compress sessions on OFFLINE status
4056 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304057 } else if (strstr(snd_card_status, "ONLINE")) {
4058 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304059 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004060 //send dts hpx license if enabled
4061 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304062 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304063 }
4064
4065 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004066 status = voice_set_parameters(adev, parms);
4067 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004068 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004070 status = platform_set_parameters(adev->platform, parms);
4071 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004072 goto done;
4073
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004074 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4075 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004076 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4078 adev->bluetooth_nrec = true;
4079 else
4080 adev->bluetooth_nrec = false;
4081 }
4082
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004083 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4084 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4086 adev->screen_off = false;
4087 else
4088 adev->screen_off = true;
4089 }
4090
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004091 ret = str_parms_get_int(parms, "rotation", &val);
4092 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004093 bool reverse_speakers = false;
4094 switch(val) {
4095 // FIXME: note that the code below assumes that the speakers are in the correct placement
4096 // relative to the user when the device is rotated 90deg from its default rotation. This
4097 // assumption is device-specific, not platform-specific like this code.
4098 case 270:
4099 reverse_speakers = true;
4100 break;
4101 case 0:
4102 case 90:
4103 case 180:
4104 break;
4105 default:
4106 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004107 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004108 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004109 if (status == 0) {
4110 if (adev->speaker_lr_swap != reverse_speakers) {
4111 adev->speaker_lr_swap = reverse_speakers;
4112 // only update the selected device if there is active pcm playback
4113 struct audio_usecase *usecase;
4114 struct listnode *node;
4115 list_for_each(node, &adev->usecase_list) {
4116 usecase = node_to_item(node, struct audio_usecase, list);
4117 if (usecase->type == PCM_PLAYBACK) {
4118 select_devices(adev, usecase->id);
4119 break;
4120 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004121 }
4122 }
4123 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004124 }
4125
Mingming Yin514a8bc2014-07-29 15:22:21 -07004126 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4127 if (ret >= 0) {
4128 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4129 adev->bt_wb_speech_enabled = true;
4130 else
4131 adev->bt_wb_speech_enabled = false;
4132 }
4133
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004134 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4135 if (ret >= 0) {
4136 val = atoi(value);
4137 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4138 ALOGV("cache new edid");
4139 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004140 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4141 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004142 /*
4143 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4144 * Per AudioPolicyManager, USB device is higher priority than WFD.
4145 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4146 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4147 * starting voice call on USB
4148 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004149 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4150 if (ret >= 0) {
4151 audio_extn_usb_add_device(val, atoi(value));
4152 }
vivek mehta344576a2016-04-12 18:56:03 -07004153 ALOGV("detected USB connect .. disable proxy");
4154 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004155 }
4156 }
4157
4158 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4159 if (ret >= 0) {
4160 val = atoi(value);
4161 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4162 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004163 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004164 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4165 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4166 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4167 if (ret >= 0) {
4168 audio_extn_usb_remove_device(val, atoi(value));
4169 }
vivek mehta344576a2016-04-12 18:56:03 -07004170 ALOGV("detected USB disconnect .. enable proxy");
4171 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004172 }
4173 }
4174
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004175 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004176
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004177done:
4178 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004179 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304180error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004181 ALOGV("%s: exit with code(%d)", __func__, status);
4182 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183}
4184
4185static char* adev_get_parameters(const struct audio_hw_device *dev,
4186 const char *keys)
4187{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004188 struct audio_device *adev = (struct audio_device *)dev;
4189 struct str_parms *reply = str_parms_create();
4190 struct str_parms *query = str_parms_create_str(keys);
4191 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304192 char value[256] = {0};
4193 int ret = 0;
4194
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004195 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004196 if (reply) {
4197 str_parms_destroy(reply);
4198 }
4199 if (query) {
4200 str_parms_destroy(query);
4201 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004202 ALOGE("adev_get_parameters: failed to create query or reply");
4203 return NULL;
4204 }
4205
Naresh Tannirud7205b62014-06-20 02:54:48 +05304206 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4207 sizeof(value));
4208 if (ret >=0) {
4209 int val = 1;
4210 pthread_mutex_lock(&adev->snd_card_status.lock);
4211 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4212 val = 0;
4213 pthread_mutex_unlock(&adev->snd_card_status.lock);
4214 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4215 goto exit;
4216 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004217
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004218 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004219 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004220 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004221 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304222 pthread_mutex_unlock(&adev->lock);
4223
Naresh Tannirud7205b62014-06-20 02:54:48 +05304224exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004225 str = str_parms_to_str(reply);
4226 str_parms_destroy(query);
4227 str_parms_destroy(reply);
4228
4229 ALOGV("%s: exit: returns - %s", __func__, str);
4230 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231}
4232
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004233static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234{
4235 return 0;
4236}
4237
4238static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4239{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004240 int ret;
4241 struct audio_device *adev = (struct audio_device *)dev;
4242 pthread_mutex_lock(&adev->lock);
4243 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004244 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004245 pthread_mutex_unlock(&adev->lock);
4246 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247}
4248
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004249static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4250 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251{
4252 return -ENOSYS;
4253}
4254
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004255static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4256 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257{
4258 return -ENOSYS;
4259}
4260
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004261static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4262 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263{
4264 return -ENOSYS;
4265}
4266
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004267static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4268 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269{
4270 return -ENOSYS;
4271}
4272
4273static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4274{
4275 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277 pthread_mutex_lock(&adev->lock);
4278 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004279 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004281 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004282 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004283 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004284 adev->current_call_output = NULL;
4285 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004286 }
4287 pthread_mutex_unlock(&adev->lock);
4288 return 0;
4289}
4290
4291static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4292{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004293 int ret;
4294
4295 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004296 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004297 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4298 pthread_mutex_unlock(&adev->lock);
4299
4300 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301}
4302
4303static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4304{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004305 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 return 0;
4307}
4308
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004309static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 const struct audio_config *config)
4311{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004312 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004314 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4315 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316}
4317
4318static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004319 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320 audio_devices_t devices,
4321 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004322 struct audio_stream_in **stream_in,
4323 audio_input_flags_t flags __unused,
4324 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004325 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326{
4327 struct audio_device *adev = (struct audio_device *)dev;
4328 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004329 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004330 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004331 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304334 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4335 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304337 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338
4339 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004340
4341 if (!in) {
4342 ALOGE("failed to allocate input stream");
4343 return -ENOMEM;
4344 }
4345
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304346 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304347 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4348 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004349 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004350 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 in->stream.common.get_sample_rate = in_get_sample_rate;
4353 in->stream.common.set_sample_rate = in_set_sample_rate;
4354 in->stream.common.get_buffer_size = in_get_buffer_size;
4355 in->stream.common.get_channels = in_get_channels;
4356 in->stream.common.get_format = in_get_format;
4357 in->stream.common.set_format = in_set_format;
4358 in->stream.common.standby = in_standby;
4359 in->stream.common.dump = in_dump;
4360 in->stream.common.set_parameters = in_set_parameters;
4361 in->stream.common.get_parameters = in_get_parameters;
4362 in->stream.common.add_audio_effect = in_add_audio_effect;
4363 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4364 in->stream.set_gain = in_set_gain;
4365 in->stream.read = in_read;
4366 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4367
4368 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004369 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371 in->standby = 1;
4372 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004373 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004374 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375
4376 /* Update config params with the requested sample rate and channels */
4377 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004378 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4379 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4380 is_low_latency = true;
4381#if LOW_LATENCY_CAPTURE_USE_CASE
4382 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4383#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004384 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004385 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004386
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004387 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004388 if (in->realtime) {
4389 in->config = pcm_config_audio_capture_rt;
4390 in->sample_rate = in->config.rate;
4391 in->af_period_multiplier = af_period_multiplier;
4392 } else {
4393 in->config = pcm_config_audio_capture;
4394 in->config.rate = config->sample_rate;
4395 in->sample_rate = config->sample_rate;
4396 in->af_period_multiplier = 1;
4397 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304398 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004400 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304401 if (adev->mode != AUDIO_MODE_IN_CALL) {
4402 ret = -EINVAL;
4403 goto err_open;
4404 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004405 if (config->sample_rate == 0)
4406 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4407 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4408 config->sample_rate != 8000) {
4409 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4410 ret = -EINVAL;
4411 goto err_open;
4412 }
4413 if (config->format == AUDIO_FORMAT_DEFAULT)
4414 config->format = AUDIO_FORMAT_PCM_16_BIT;
4415 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4416 config->format = AUDIO_FORMAT_PCM_16_BIT;
4417 ret = -EINVAL;
4418 goto err_open;
4419 }
4420
4421 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4422 in->config = pcm_config_afe_proxy_record;
4423 in->config.channels = channel_count;
4424 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304425 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304426 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4427 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004428 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004429 audio_extn_compr_cap_format_supported(config->format) &&
4430 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004431 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004432 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304433 /* restrict 24 bit capture for unprocessed source only
4434 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4435 */
4436 if (config->format == AUDIO_FORMAT_DEFAULT) {
4437 config->format = AUDIO_FORMAT_PCM_16_BIT;
4438 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4439 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4440 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4441 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4442 bool ret_error = false;
4443 in->bit_width = 24;
4444 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4445 from HAL is 24_packed and 8_24
4446 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4447 24_packed return error indicating supported format is 24_packed
4448 *> In case of any other source requesting 24 bit or float return error
4449 indicating format supported is 16 bit only.
4450
4451 on error flinger will retry with supported format passed
4452 */
4453 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4454 (source != AUDIO_SOURCE_CAMCORDER)) {
4455 config->format = AUDIO_FORMAT_PCM_16_BIT;
4456 if( config->sample_rate > 48000)
4457 config->sample_rate = 48000;
4458 ret_error = true;
4459 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4460 in->config.format = PCM_FORMAT_S24_3LE;
4461 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4462 in->config.format = PCM_FORMAT_S24_LE;
4463 } else {
4464 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4465 ret_error = true;
4466 }
4467
4468 if (ret_error) {
4469 ret = -EINVAL;
4470 goto err_open;
4471 }
4472 }
4473
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004474 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004475 if (!in->realtime) {
4476 in->format = config->format;
4477 frame_size = audio_stream_in_frame_size(&in->stream);
4478 buffer_size = get_input_buffer_size(config->sample_rate,
4479 config->format,
4480 channel_count,
4481 is_low_latency);
4482 in->config.period_size = buffer_size / frame_size;
4483 }
4484
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004485 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4486 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4487 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004488 (in->config.rate == 8000 || in->config.rate == 16000 ||
4489 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004490 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4491 voice_extn_compress_voip_open_input_stream(in);
4492 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004494
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004495 /* This stream could be for sound trigger lab,
4496 get sound trigger pcm if present */
4497 audio_extn_sound_trigger_check_and_get_session(in);
4498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004499 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004500 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004501 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502
4503err_open:
4504 free(in);
4505 *stream_in = NULL;
4506 return ret;
4507}
4508
4509static void adev_close_input_stream(struct audio_hw_device *dev,
4510 struct audio_stream_in *stream)
4511{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004512 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004513 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004514 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304515
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304516 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004517
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304518 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004519 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304520
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004521 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304522 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004523 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304524 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004525 if (ret != 0)
4526 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4527 __func__, ret);
4528 } else
4529 in_standby(&stream->common);
4530
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004531 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004532 audio_extn_ssr_deinit();
4533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004534
Mingming Yine62d7842013-10-25 16:26:03 -07004535 if(audio_extn_compr_cap_enabled() &&
4536 audio_extn_compr_cap_format_supported(in->config.format))
4537 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004538
Mingming Yinfd7607b2016-01-22 12:48:44 -08004539 if (in->is_st_session) {
4540 ALOGV("%s: sound trigger pcm stop lab", __func__);
4541 audio_extn_sound_trigger_stop_lab(in);
4542 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004543 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 return;
4545}
4546
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004547static int adev_dump(const audio_hw_device_t *device __unused,
4548 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549{
4550 return 0;
4551}
4552
4553static int adev_close(hw_device_t *device)
4554{
4555 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004556
4557 if (!adev)
4558 return 0;
4559
4560 pthread_mutex_lock(&adev_init_lock);
4561
4562 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004563 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004564 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004565 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004566 audio_route_free(adev->audio_route);
4567 free(adev->snd_dev_ref_cnt);
4568 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004569 if (adev->adm_deinit)
4570 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004571 free(device);
4572 adev = NULL;
4573 }
4574 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576 return 0;
4577}
4578
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004579/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4580 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4581 * just that it _might_ work.
4582 */
4583static int period_size_is_plausible_for_low_latency(int period_size)
4584{
4585 switch (period_size) {
4586 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004587 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004588 case 240:
4589 case 320:
4590 case 480:
4591 return 1;
4592 default:
4593 return 0;
4594 }
4595}
4596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597static int adev_open(const hw_module_t *module, const char *name,
4598 hw_device_t **device)
4599{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004600 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4602
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004603 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004604 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004605 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004606 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004607 ALOGD("%s: returning existing instance of adev", __func__);
4608 ALOGD("%s: exit", __func__);
4609 pthread_mutex_unlock(&adev_init_lock);
4610 return 0;
4611 }
4612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 adev = calloc(1, sizeof(struct audio_device));
4614
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004615 if (!adev) {
4616 pthread_mutex_unlock(&adev_init_lock);
4617 return -ENOMEM;
4618 }
4619
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004620 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4623 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4624 adev->device.common.module = (struct hw_module_t *)module;
4625 adev->device.common.close = adev_close;
4626
4627 adev->device.init_check = adev_init_check;
4628 adev->device.set_voice_volume = adev_set_voice_volume;
4629 adev->device.set_master_volume = adev_set_master_volume;
4630 adev->device.get_master_volume = adev_get_master_volume;
4631 adev->device.set_master_mute = adev_set_master_mute;
4632 adev->device.get_master_mute = adev_get_master_mute;
4633 adev->device.set_mode = adev_set_mode;
4634 adev->device.set_mic_mute = adev_set_mic_mute;
4635 adev->device.get_mic_mute = adev_get_mic_mute;
4636 adev->device.set_parameters = adev_set_parameters;
4637 adev->device.get_parameters = adev_get_parameters;
4638 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4639 adev->device.open_output_stream = adev_open_output_stream;
4640 adev->device.close_output_stream = adev_close_output_stream;
4641 adev->device.open_input_stream = adev_open_input_stream;
4642 adev->device.close_input_stream = adev_close_input_stream;
4643 adev->device.dump = adev_dump;
4644
4645 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004647 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004648 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004651 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004652 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004653 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004654 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004655 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004656 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004657 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004658 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304659 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304660 adev->perf_lock_opts[0] = 0x101;
4661 adev->perf_lock_opts[1] = 0x20E;
4662 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304663
4664 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4665 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004667 adev->platform = platform_init(adev);
4668 if (!adev->platform) {
4669 free(adev->snd_dev_ref_cnt);
4670 free(adev);
4671 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4672 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004673 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004674 return -EINVAL;
4675 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004676
Naresh Tanniru4c630392014-05-12 01:05:52 +05304677 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4678
Eric Laurentc4aef752013-09-12 17:45:53 -07004679 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4680 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4681 if (adev->visualizer_lib == NULL) {
4682 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4683 } else {
4684 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4685 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004686 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004687 "visualizer_hal_start_output");
4688 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004689 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004690 "visualizer_hal_stop_output");
4691 }
4692 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004693 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004694 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004695
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004696 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4697 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4698 if (adev->offload_effects_lib == NULL) {
4699 ALOGE("%s: DLOPEN failed for %s", __func__,
4700 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4701 } else {
4702 ALOGV("%s: DLOPEN successful for %s", __func__,
4703 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4704 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304705 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004706 "offload_effects_bundle_hal_start_output");
4707 adev->offload_effects_stop_output =
4708 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4709 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004710 adev->offload_effects_set_hpx_state =
4711 (int (*)(bool))dlsym(adev->offload_effects_lib,
4712 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304713 adev->offload_effects_get_parameters =
4714 (void (*)(struct str_parms *, struct str_parms *))
4715 dlsym(adev->offload_effects_lib,
4716 "offload_effects_bundle_get_parameters");
4717 adev->offload_effects_set_parameters =
4718 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4719 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004720 }
4721 }
4722
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004723 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4724 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4725 if (adev->adm_lib == NULL) {
4726 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4727 } else {
4728 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4729 adev->adm_init = (adm_init_t)
4730 dlsym(adev->adm_lib, "adm_init");
4731 adev->adm_deinit = (adm_deinit_t)
4732 dlsym(adev->adm_lib, "adm_deinit");
4733 adev->adm_register_input_stream = (adm_register_input_stream_t)
4734 dlsym(adev->adm_lib, "adm_register_input_stream");
4735 adev->adm_register_output_stream = (adm_register_output_stream_t)
4736 dlsym(adev->adm_lib, "adm_register_output_stream");
4737 adev->adm_deregister_stream = (adm_deregister_stream_t)
4738 dlsym(adev->adm_lib, "adm_deregister_stream");
4739 adev->adm_request_focus = (adm_request_focus_t)
4740 dlsym(adev->adm_lib, "adm_request_focus");
4741 adev->adm_abandon_focus = (adm_abandon_focus_t)
4742 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004743 adev->adm_set_config = (adm_set_config_t)
4744 dlsym(adev->adm_lib, "adm_set_config");
4745 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4746 dlsym(adev->adm_lib, "adm_request_focus_v2");
4747 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4748 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4749 adev->adm_on_routing_change = (adm_on_routing_change_t)
4750 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004751 }
4752 }
4753
Mingming Yin514a8bc2014-07-29 15:22:21 -07004754 adev->bt_wb_speech_enabled = false;
4755
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004756 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757 *device = &adev->device.common;
4758
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004759 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4760 &adev->streams_output_cfg_list);
4761
Kiran Kandi910e1862013-10-29 13:29:42 -07004762 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004763
4764 char value[PROPERTY_VALUE_MAX];
4765 int trial;
4766 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4767 trial = atoi(value);
4768 if (period_size_is_plausible_for_low_latency(trial)) {
4769 pcm_config_low_latency.period_size = trial;
4770 pcm_config_low_latency.start_threshold = trial / 4;
4771 pcm_config_low_latency.avail_min = trial / 4;
4772 configured_low_latency_capture_period_size = trial;
4773 }
4774 }
4775 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4776 trial = atoi(value);
4777 if (period_size_is_plausible_for_low_latency(trial)) {
4778 configured_low_latency_capture_period_size = trial;
4779 }
4780 }
4781
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004782 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4783 af_period_multiplier = atoi(value);
4784 if (af_period_multiplier < 0)
4785 af_period_multiplier = 2;
4786 else if (af_period_multiplier > 4)
4787 af_period_multiplier = 4;
4788
4789 ALOGV("new period_multiplier = %d", af_period_multiplier);
4790 }
4791
vivek mehta446c3962015-09-14 10:57:35 -07004792 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004793 pthread_mutex_unlock(&adev_init_lock);
4794
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004795 if (adev->adm_init)
4796 adev->adm_data = adev->adm_init();
4797
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304798 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004799 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800 return 0;
4801}
4802
4803static struct hw_module_methods_t hal_module_methods = {
4804 .open = adev_open,
4805};
4806
4807struct audio_module HAL_MODULE_INFO_SYM = {
4808 .common = {
4809 .tag = HARDWARE_MODULE_TAG,
4810 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4811 .hal_api_version = HARDWARE_HAL_API_VERSION,
4812 .id = AUDIO_HARDWARE_MODULE_ID,
4813 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004814 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815 .methods = &hal_module_methods,
4816 },
4817};