blob: 65c285fc9bb2c5c4454574f413f86844da7f06b8 [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
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530719 if (((SND_DEVICE_OUT_BT_A2DP == snd_device) ||
720 (SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device))
721 && (audio_extn_a2dp_start_playback() < 0)) {
722 ALOGE(" fail to configure A2dp control path ");
723 return -EINVAL;
724 }
725
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800726 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
727 audio_extn_spkr_prot_is_enabled()) {
728 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700729 adev->snd_dev_ref_cnt[snd_device]--;
730 return -EINVAL;
731 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200732 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800733 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800734 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200735 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800736 return -EINVAL;
737 }
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530738 } else if (platform_can_split_snd_device(adev->platform, snd_device,
739 &num_devices, new_snd_devices)) {
740 for (i = 0; i < num_devices; i++) {
741 enable_snd_device(adev, new_snd_devices[i]);
742 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800743 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700744 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700745 /* due to the possibility of calibration overwrite between listen
746 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700747 audio_extn_sound_trigger_update_device_status(snd_device,
748 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530749 audio_extn_listen_update_device_status(snd_device,
750 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700751 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700752 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700753 audio_extn_sound_trigger_update_device_status(snd_device,
754 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530755 audio_extn_listen_update_device_status(snd_device,
756 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700757 return -EINVAL;
758 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300759 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700760 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530761
762 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
763 !adev->native_playback_enabled &&
764 audio_is_true_native_stream_active(adev)) {
765 ALOGD("%s: %d: napb: enabling native mode in hardware",
766 __func__, __LINE__);
767 audio_route_apply_and_update_path(adev->audio_route,
768 "true-native-mode");
769 adev->native_playback_enabled = true;
770 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800772 return 0;
773}
774
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700775int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700776 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800777{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530778 int i, num_devices = 0;
779 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700780 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
781
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800782 if (snd_device < SND_DEVICE_MIN ||
783 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800784 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800785 return -EINVAL;
786 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
788 ALOGE("%s: device ref cnt is already 0", __func__);
789 return -EINVAL;
790 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700791
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700793
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700794 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
795 ALOGE("%s: Invalid sound device returned", __func__);
796 return -EINVAL;
797 }
798
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700800 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530801
802 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) ||
803 (SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device))
804 audio_extn_a2dp_stop_playback();
805
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800806 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
807 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700808 audio_extn_spkr_prot_stop_processing(snd_device);
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530809 } else if (platform_can_split_snd_device(adev->platform, snd_device,
810 &num_devices, new_snd_devices)) {
811 for (i = 0; i < num_devices; i++) {
812 disable_snd_device(adev, new_snd_devices[i]);
813 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300814 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700815 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300816 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700817
Ashish Jain81eb2a82015-05-13 10:52:34 +0530818 if (snd_device == SND_DEVICE_OUT_HDMI)
819 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530820 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
821 adev->native_playback_enabled) {
822 ALOGD("%s: %d: napb: disabling native mode in hardware",
823 __func__, __LINE__);
824 audio_route_reset_and_update_path(adev->audio_route,
825 "true-native-mode");
826 adev->native_playback_enabled = false;
827 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530828
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200829 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700830 audio_extn_sound_trigger_update_device_status(snd_device,
831 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530832 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800833 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836 return 0;
837}
838
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530840 struct audio_usecase *uc_info,
841 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700842{
843 struct listnode *node;
844 struct audio_usecase *usecase;
845 bool switch_device[AUDIO_USECASE_MAX];
846 int i, num_uc_to_switch = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530847 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700848 /*
849 * This function is to make sure that all the usecases that are active on
850 * the hardware codec backend are always routed to any one device that is
851 * handled by the hardware codec.
852 * For example, if low-latency and deep-buffer usecases are currently active
853 * on speaker and out_set_parameters(headset) is received on low-latency
854 * output, then we have to make sure deep-buffer is also switched to headset,
855 * because of the limitation that both the devices cannot be enabled
856 * at the same time as they share the same backend.
857 */
Mingming Yin3ee55c62014-08-04 14:23:35 -0700858 /*
859 * This call is to check if we need to force routing for a particular stream
860 * If there is a backend configuration change for the device when a
861 * new stream starts, then ADM needs to be closed and re-opened with the new
862 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800863 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -0700864 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800865 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
866 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530867 /* For a2dp device reconfigure all active sessions
868 * with new AFE encoder format based on a2dp state
869 */
870 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
871 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
872 audio_extn_a2dp_is_force_device_switch()) {
873 force_routing = true;
874 force_restart_session = true;
875 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530876 ALOGD("%s:becf: force routing %d", __func__, force_routing);
877
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700878 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800879 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -0800880 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 for (i = 0; i < AUDIO_USECASE_MAX; i++)
882 switch_device[i] = false;
883
884 list_for_each(node, &adev->usecase_list) {
885 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -0800886
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530887 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
888 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530889 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530890 platform_get_snd_device_name(usecase->out_snd_device),
891 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800892 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530893 usecase != uc_info &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530894 (usecase->out_snd_device != snd_device || force_routing) &&
895 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
896 force_restart_session) &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530897 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
898 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
899 __func__, use_case_table[usecase->id],
900 platform_get_snd_device_name(usecase->out_snd_device));
901 disable_audio_route(adev, usecase);
902 switch_device[usecase->id] = true;
903 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 }
905 }
906
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530907 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
908 num_uc_to_switch);
909
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700911 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700912
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530913 /* Make sure the previous devices to be disabled first and then enable the
914 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700915 list_for_each(node, &adev->usecase_list) {
916 usecase = node_to_item(node, struct audio_usecase, list);
917 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700918 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 }
920 }
921
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700922 list_for_each(node, &adev->usecase_list) {
923 usecase = node_to_item(node, struct audio_usecase, list);
924 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700925 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700926 }
927 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700928
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700929 /* Re-route all the usecases on the shared backend other than the
930 specified usecase to new snd devices */
931 list_for_each(node, &adev->usecase_list) {
932 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530933 /* Update the out_snd_device only before enabling the audio route */
934 if (switch_device[usecase->id]) {
935 usecase->out_snd_device = snd_device;
936 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530937 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530938 use_case_table[usecase->id],
939 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530940 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530941 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 }
943 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 }
945}
946
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530947static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700948 struct audio_usecase *uc_info,
949 snd_device_t snd_device)
950{
951 struct listnode *node;
952 struct audio_usecase *usecase;
953 bool switch_device[AUDIO_USECASE_MAX];
954 int i, num_uc_to_switch = 0;
955
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530956 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
957 snd_device);
958 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700959 /*
960 * This function is to make sure that all the active capture usecases
961 * are always routed to the same input sound device.
962 * For example, if audio-record and voice-call usecases are currently
963 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
964 * is received for voice call then we have to make sure that audio-record
965 * usecase is also switched to earpiece i.e. voice-dmic-ef,
966 * because of the limitation that two devices cannot be enabled
967 * at the same time if they share the same backend.
968 */
969 for (i = 0; i < AUDIO_USECASE_MAX; i++)
970 switch_device[i] = false;
971
972 list_for_each(node, &adev->usecase_list) {
973 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800974 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530976 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700977 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530978 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +0800979 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700980 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700981 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
982 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700983 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700984 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700985 switch_device[usecase->id] = true;
986 num_uc_to_switch++;
987 }
988 }
989
990 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700991 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530993 /* Make sure the previous devices to be disabled first and then enable the
994 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700995 list_for_each(node, &adev->usecase_list) {
996 usecase = node_to_item(node, struct audio_usecase, list);
997 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700998 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800999 }
1000 }
1001
1002 list_for_each(node, &adev->usecase_list) {
1003 usecase = node_to_item(node, struct audio_usecase, list);
1004 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001005 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001006 }
1007 }
1008
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001009 /* Re-route all the usecases on the shared backend other than the
1010 specified usecase to new snd devices */
1011 list_for_each(node, &adev->usecase_list) {
1012 usecase = node_to_item(node, struct audio_usecase, list);
1013 /* Update the in_snd_device only before enabling the audio route */
1014 if (switch_device[usecase->id] ) {
1015 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001016 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301017 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001018 }
1019 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001020 }
1021}
1022
Mingming Yin3a941d42016-02-17 18:08:05 -08001023static void reset_hdmi_sink_caps(struct stream_out *out) {
1024 int i = 0;
1025
1026 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1027 out->supported_channel_masks[i] = 0;
1028 }
1029 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1030 out->supported_formats[i] = 0;
1031 }
1032 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1033 out->supported_sample_rates[i] = 0;
1034 }
1035}
1036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001038static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039{
Mingming Yin3a941d42016-02-17 18:08:05 -08001040 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001041 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042
Mingming Yin3a941d42016-02-17 18:08:05 -08001043 reset_hdmi_sink_caps(out);
1044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001045 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001047 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001048 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001049 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1050 case 6:
1051 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1052 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1053 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1054 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1055 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1056 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057 break;
1058 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001059 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001060 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061 break;
1062 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001063
1064 // check channel format caps
1065 i = 0;
1066 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1067 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1068 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1069 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1070 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1071 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1072 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1073 }
1074
1075 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1076 ALOGV(":%s HDMI supports DTS format", __func__);
1077 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1078 }
1079
1080 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1081 ALOGV(":%s HDMI supports DTS HD format", __func__);
1082 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1083 }
1084
1085
1086 // check sample rate caps
1087 i = 0;
1088 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1089 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1090 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1091 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1092 }
1093 }
1094
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001095 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096}
1097
Alexy Josephb1379942016-01-29 15:49:38 -08001098audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001099 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001100{
1101 struct audio_usecase *usecase;
1102 struct listnode *node;
1103
1104 list_for_each(node, &adev->usecase_list) {
1105 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001106 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001107 ALOGV("%s: usecase id %d", __func__, usecase->id);
1108 return usecase->id;
1109 }
1110 }
1111 return USECASE_INVALID;
1112}
1113
Alexy Josephb1379942016-01-29 15:49:38 -08001114struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001115 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116{
1117 struct audio_usecase *usecase;
1118 struct listnode *node;
1119
1120 list_for_each(node, &adev->usecase_list) {
1121 usecase = node_to_item(node, struct audio_usecase, list);
1122 if (usecase->id == uc_id)
1123 return usecase;
1124 }
1125 return NULL;
1126}
1127
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301128/*
1129 * is a true native playback active
1130 */
1131bool audio_is_true_native_stream_active(struct audio_device *adev)
1132{
1133 bool active = false;
1134 int i = 0;
1135 struct listnode *node;
1136
1137 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1138 ALOGV("%s:napb: not in true mode or non hdphones device",
1139 __func__);
1140 active = false;
1141 goto exit;
1142 }
1143
1144 list_for_each(node, &adev->usecase_list) {
1145 struct audio_usecase *uc;
1146 uc = node_to_item(node, struct audio_usecase, list);
1147 struct stream_out *curr_out =
1148 (struct stream_out*) uc->stream.out;
1149
1150 if (curr_out && PCM_PLAYBACK == uc->type) {
1151 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1152 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1153 uc->id, curr_out->sample_rate,
1154 curr_out->bit_width,
1155 platform_get_snd_device_name(uc->out_snd_device));
1156
1157 if (is_offload_usecase(uc->id) &&
1158 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1159 active = true;
1160 ALOGD("%s:napb:native stream detected", __func__);
1161 }
1162 }
1163 }
1164exit:
1165 return active;
1166}
1167
1168
1169static bool force_device_switch(struct audio_usecase *usecase)
1170{
1171 bool ret = false;
1172 bool is_it_true_mode = false;
1173
1174 if (is_offload_usecase(usecase->id) &&
1175 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001176 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1177 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1178 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301179 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1180 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1181 (!is_it_true_mode && adev->native_playback_enabled)){
1182 ret = true;
1183 ALOGD("napb: time to toggle native mode");
1184 }
1185 }
1186
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301187 // Force all a2dp output devices to reconfigure for proper AFE encode format
1188 if((usecase->stream.out) &&
1189 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1190 audio_extn_a2dp_is_force_device_switch()) {
1191 ALOGD("Force a2dp device switch to update new encoder config");
1192 ret = true;
1193 }
1194
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301195 return ret;
1196}
1197
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001198int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001199{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001200 snd_device_t out_snd_device = SND_DEVICE_NONE;
1201 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 struct audio_usecase *usecase = NULL;
1203 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001204 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001205 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001206 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001207 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001208
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301209 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1210
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 usecase = get_usecase_from_list(adev, uc_id);
1212 if (usecase == NULL) {
1213 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1214 return -EINVAL;
1215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001216
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001217 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001218 (usecase->type == VOIP_CALL) ||
1219 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001220 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001221 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001222 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001223 usecase->devices = usecase->stream.out->devices;
1224 } else {
1225 /*
1226 * If the voice call is active, use the sound devices of voice call usecase
1227 * so that it would not result any device switch. All the usecases will
1228 * be switched to new device when select_devices() is called for voice call
1229 * usecase. This is to avoid switching devices for voice call when
1230 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001231 * choose voice call device only if the use case device is
1232 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001233 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001234 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001235 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001236 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001237 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1238 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301239 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1240 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001241 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242 in_snd_device = vc_usecase->in_snd_device;
1243 out_snd_device = vc_usecase->out_snd_device;
1244 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001245 } else if (voice_extn_compress_voip_is_active(adev)) {
1246 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001247 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001248 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1249 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001250 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001251 in_snd_device = voip_usecase->in_snd_device;
1252 out_snd_device = voip_usecase->out_snd_device;
1253 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001254 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001255 hfp_ucid = audio_extn_hfp_get_usecase();
1256 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001257 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001258 in_snd_device = hfp_usecase->in_snd_device;
1259 out_snd_device = hfp_usecase->out_snd_device;
1260 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001261 }
1262 if (usecase->type == PCM_PLAYBACK) {
1263 usecase->devices = usecase->stream.out->devices;
1264 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001265 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001266 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001267 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001268 if (usecase->stream.out == adev->primary_output &&
1269 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001270 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001271 select_devices(adev, adev->active_input->usecase);
1272 }
1273 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 } else if (usecase->type == PCM_CAPTURE) {
1275 usecase->devices = usecase->stream.in->device;
1276 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001277 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001278 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001279 if (adev->active_input &&
1280 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301281 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1282 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1283 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001284 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001285 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001286 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1287 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001288 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001289 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001290 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001291 }
1292 }
1293
1294 if (out_snd_device == usecase->out_snd_device &&
1295 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301296
1297 if (!force_device_switch(usecase))
1298 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001299 }
1300
sangwoobc677242013-08-08 16:53:43 +09001301 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001302 out_snd_device, platform_get_snd_device_name(out_snd_device),
1303 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305 /*
1306 * Limitation: While in call, to do a device switch we need to disable
1307 * and enable both RX and TX devices though one of them is same as current
1308 * device.
1309 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001310 if ((usecase->type == VOICE_CALL) &&
1311 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1312 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001313 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001314 }
1315
1316 if (((usecase->type == VOICE_CALL) ||
1317 (usecase->type == VOIP_CALL)) &&
1318 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1319 /* Disable sidetone only if voice/voip call already exists */
1320 if (voice_is_call_state_active(adev) ||
1321 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001322 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001323 }
1324
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 /* Disable current sound devices */
1326 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001327 disable_audio_route(adev, usecase);
1328 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329 }
1330
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001331 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001332 disable_audio_route(adev, usecase);
1333 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001334 }
1335
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001336 /* Applicable only on the targets that has external modem.
1337 * New device information should be sent to modem before enabling
1338 * the devices to reduce in-call device switch time.
1339 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001340 if ((usecase->type == VOICE_CALL) &&
1341 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1342 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001343 status = platform_switch_voice_call_enable_device_config(adev->platform,
1344 out_snd_device,
1345 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001346 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001347
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001348 /* Enable new sound devices */
1349 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001350 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001351 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 }
1353
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001354 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301355 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001356 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001357 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001358
Avinash Vaish71a8b972014-07-24 15:36:33 +05301359 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001360 status = platform_switch_voice_call_device_post(adev->platform,
1361 out_snd_device,
1362 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301363 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001364 /* Enable sidetone only if voice/voip call already exists */
1365 if (voice_is_call_state_active(adev) ||
1366 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001367 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301368 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001369
sangwoo170731f2013-06-08 15:36:36 +09001370 usecase->in_snd_device = in_snd_device;
1371 usecase->out_snd_device = out_snd_device;
1372
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301373 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001374 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301375 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001376 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301377 usecase->stream.out->flags,
1378 usecase->stream.out->format,
1379 usecase->stream.out->sample_rate,
1380 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301381 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301382 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001383 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301384 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001385
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001386 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001387
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001388 /* Applicable only on the targets that has external modem.
1389 * Enable device command should be sent to modem only after
1390 * enabling voice call mixer controls
1391 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001392 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001393 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1394 out_snd_device,
1395 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301396 ALOGD("%s: done",__func__);
1397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001398 return status;
1399}
1400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401static int stop_input_stream(struct stream_in *in)
1402{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301403 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 struct audio_usecase *uc_info;
1405 struct audio_device *adev = in->dev;
1406
Eric Laurentc8400632013-02-14 19:04:54 -08001407 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001408
Eric Laurent994a6932013-07-17 11:51:42 -07001409 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001410 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411 uc_info = get_usecase_from_list(adev, in->usecase);
1412 if (uc_info == NULL) {
1413 ALOGE("%s: Could not find the usecase (%d) in the list",
1414 __func__, in->usecase);
1415 return -EINVAL;
1416 }
1417
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001418 /* Close in-call recording streams */
1419 voice_check_and_stop_incall_rec_usecase(adev, in);
1420
Eric Laurent150dbfe2013-02-27 14:31:02 -08001421 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001422 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001423
1424 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001425 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001427 list_remove(&uc_info->list);
1428 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429
Eric Laurent994a6932013-07-17 11:51:42 -07001430 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 return ret;
1432}
1433
1434int start_input_stream(struct stream_in *in)
1435{
1436 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001437 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 struct audio_usecase *uc_info;
1439 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301440 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441
Mingming Yin2664a5b2015-09-03 10:53:11 -07001442 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1443 if (get_usecase_from_list(adev, usecase) == NULL)
1444 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301445 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1446 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001447
Naresh Tanniru80659832014-06-04 18:17:56 +05301448
1449 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301450 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301451 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301452 goto error_config;
1453 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301454
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001455 /* Check if source matches incall recording usecase criteria */
1456 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1457 if (ret)
1458 goto error_config;
1459 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001460 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1461
1462 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1463 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1464 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001465 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001466 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001467
Eric Laurentb23d5282013-05-14 15:27:20 -07001468 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 if (in->pcm_device_id < 0) {
1470 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1471 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001472 ret = -EINVAL;
1473 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475
1476 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001478
1479 if (!uc_info) {
1480 ret = -ENOMEM;
1481 goto error_config;
1482 }
1483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484 uc_info->id = in->usecase;
1485 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001486 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001487 uc_info->devices = in->device;
1488 uc_info->in_snd_device = SND_DEVICE_NONE;
1489 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001491 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301492 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1493 adev->perf_lock_opts,
1494 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301497 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1498 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001499
1500 unsigned int flags = PCM_IN;
1501 unsigned int pcm_open_retry_count = 0;
1502
1503 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1504 flags |= PCM_MMAP | PCM_NOIRQ;
1505 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001506 } else if (in->realtime) {
1507 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001508 }
1509
1510 while (1) {
1511 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1512 flags, &in->config);
1513 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1514 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1515 if (in->pcm != NULL) {
1516 pcm_close(in->pcm);
1517 in->pcm = NULL;
1518 }
1519 if (pcm_open_retry_count-- == 0) {
1520 ret = -EIO;
1521 goto error_open;
1522 }
1523 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1524 continue;
1525 }
1526 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001528
1529 ALOGV("%s: pcm_prepare", __func__);
1530 ret = pcm_prepare(in->pcm);
1531 if (ret < 0) {
1532 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1533 pcm_close(in->pcm);
1534 in->pcm = NULL;
1535 goto error_open;
1536 }
1537
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001538 register_in_stream(in);
1539 if (in->realtime) {
1540 ret = pcm_start(in->pcm);
1541 if (ret < 0)
1542 goto error_open;
1543 }
1544
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301545 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001546 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001547
Eric Laurentc8400632013-02-14 19:04:54 -08001548 return ret;
1549
1550error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301551 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001553error_config:
1554 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301555 /*
1556 * sleep 50ms to allow sufficient time for kernel
1557 * drivers to recover incases like SSR.
1558 */
1559 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001561
1562 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563}
1564
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001565void lock_input_stream(struct stream_in *in)
1566{
1567 pthread_mutex_lock(&in->pre_lock);
1568 pthread_mutex_lock(&in->lock);
1569 pthread_mutex_unlock(&in->pre_lock);
1570}
1571
1572void lock_output_stream(struct stream_out *out)
1573{
1574 pthread_mutex_lock(&out->pre_lock);
1575 pthread_mutex_lock(&out->lock);
1576 pthread_mutex_unlock(&out->pre_lock);
1577}
1578
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001579/* must be called with out->lock locked */
1580static int send_offload_cmd_l(struct stream_out* out, int command)
1581{
1582 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1583
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001584 if (!cmd) {
1585 ALOGE("failed to allocate mem for command 0x%x", command);
1586 return -ENOMEM;
1587 }
1588
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 ALOGVV("%s %d", __func__, command);
1590
1591 cmd->cmd = command;
1592 list_add_tail(&out->offload_cmd_list, &cmd->node);
1593 pthread_cond_signal(&out->offload_cond);
1594 return 0;
1595}
1596
1597/* must be called iwth out->lock locked */
1598static void stop_compressed_output_l(struct stream_out *out)
1599{
1600 out->offload_state = OFFLOAD_STATE_IDLE;
1601 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001602 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603 if (out->compr != NULL) {
1604 compress_stop(out->compr);
1605 while (out->offload_thread_blocked) {
1606 pthread_cond_wait(&out->cond, &out->lock);
1607 }
1608 }
1609}
1610
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001611bool is_offload_usecase(audio_usecase_t uc_id)
1612{
1613 unsigned int i;
1614 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1615 if (uc_id == offload_usecases[i])
1616 return true;
1617 }
1618 return false;
1619}
1620
vivek mehta446c3962015-09-14 10:57:35 -07001621static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001622{
vivek mehta446c3962015-09-14 10:57:35 -07001623 audio_usecase_t ret_uc = USECASE_INVALID;
1624 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 if (!adev->multi_offload_enable) {
1627 if (is_direct_pcm)
1628 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1629 else
1630 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001631
vivek mehta446c3962015-09-14 10:57:35 -07001632 pthread_mutex_lock(&adev->lock);
1633 if (get_usecase_from_list(adev, ret_uc) != NULL)
1634 ret_uc = USECASE_INVALID;
1635 pthread_mutex_unlock(&adev->lock);
1636
1637 return ret_uc;
1638 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001639
1640 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001641 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1642 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1643 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1644 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001645 break;
1646 }
1647 }
vivek mehta446c3962015-09-14 10:57:35 -07001648
1649 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1650 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001651}
1652
1653static void free_offload_usecase(struct audio_device *adev,
1654 audio_usecase_t uc_id)
1655{
vivek mehta446c3962015-09-14 10:57:35 -07001656 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001657 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001658
1659 if (!adev->multi_offload_enable)
1660 return;
1661
1662 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1663 if (offload_usecases[offload_uc_index] == uc_id) {
1664 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001665 break;
1666 }
1667 }
1668 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1669}
1670
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671static void *offload_thread_loop(void *context)
1672{
1673 struct stream_out *out = (struct stream_out *) context;
1674 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001675 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001676
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001677 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1678 set_sched_policy(0, SP_FOREGROUND);
1679 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1680
1681 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001682 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001683 for (;;) {
1684 struct offload_cmd *cmd = NULL;
1685 stream_callback_event_t event;
1686 bool send_callback = false;
1687
1688 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1689 __func__, list_empty(&out->offload_cmd_list),
1690 out->offload_state);
1691 if (list_empty(&out->offload_cmd_list)) {
1692 ALOGV("%s SLEEPING", __func__);
1693 pthread_cond_wait(&out->offload_cond, &out->lock);
1694 ALOGV("%s RUNNING", __func__);
1695 continue;
1696 }
1697
1698 item = list_head(&out->offload_cmd_list);
1699 cmd = node_to_item(item, struct offload_cmd, node);
1700 list_remove(item);
1701
1702 ALOGVV("%s STATE %d CMD %d out->compr %p",
1703 __func__, out->offload_state, cmd->cmd, out->compr);
1704
1705 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1706 free(cmd);
1707 break;
1708 }
1709
1710 if (out->compr == NULL) {
1711 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001712 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 pthread_cond_signal(&out->cond);
1714 continue;
1715 }
1716 out->offload_thread_blocked = true;
1717 pthread_mutex_unlock(&out->lock);
1718 send_callback = false;
1719 switch(cmd->cmd) {
1720 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001721 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001723 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001724 send_callback = true;
1725 event = STREAM_CBK_EVENT_WRITE_READY;
1726 break;
1727 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001728 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301729 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001730 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301731 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001732 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301733 if (ret < 0)
1734 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301735 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301736 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001737 compress_drain(out->compr);
1738 else
1739 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301740 if (ret != -ENETRESET) {
1741 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301742 pthread_mutex_lock(&out->lock);
1743 out->send_new_metadata = 1;
1744 out->send_next_track_params = true;
1745 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301746 event = STREAM_CBK_EVENT_DRAIN_READY;
1747 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1748 } else
1749 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 break;
1751 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001752 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001754 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 send_callback = true;
1756 event = STREAM_CBK_EVENT_DRAIN_READY;
1757 break;
1758 default:
1759 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1760 break;
1761 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001762 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001763 out->offload_thread_blocked = false;
1764 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001765 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001766 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001768 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001769 free(cmd);
1770 }
1771
1772 pthread_cond_signal(&out->cond);
1773 while (!list_empty(&out->offload_cmd_list)) {
1774 item = list_head(&out->offload_cmd_list);
1775 list_remove(item);
1776 free(node_to_item(item, struct offload_cmd, node));
1777 }
1778 pthread_mutex_unlock(&out->lock);
1779
1780 return NULL;
1781}
1782
1783static int create_offload_callback_thread(struct stream_out *out)
1784{
1785 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1786 list_init(&out->offload_cmd_list);
1787 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1788 offload_thread_loop, out);
1789 return 0;
1790}
1791
1792static int destroy_offload_callback_thread(struct stream_out *out)
1793{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001794 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 stop_compressed_output_l(out);
1796 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1797
1798 pthread_mutex_unlock(&out->lock);
1799 pthread_join(out->offload_thread, (void **) NULL);
1800 pthread_cond_destroy(&out->offload_cond);
1801
1802 return 0;
1803}
1804
Mingming Yin21854652016-04-13 11:54:02 -07001805static bool allow_hdmi_channel_config(struct audio_device *adev,
1806 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001807{
1808 struct listnode *node;
1809 struct audio_usecase *usecase;
1810 bool ret = true;
1811
Mingming Yin21854652016-04-13 11:54:02 -07001812 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1813 ret = false;
1814 goto exit;
1815 }
1816
1817 if (audio_extn_passthru_is_active()) {
1818 ALOGI("%s: Compress audio passthrough is active,"
1819 "no HDMI config change allowed", __func__);
1820 ret = false;
1821 goto exit;
1822 }
1823
Eric Laurent07eeafd2013-10-06 12:52:49 -07001824 list_for_each(node, &adev->usecase_list) {
1825 usecase = node_to_item(node, struct audio_usecase, list);
1826 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1827 /*
1828 * If voice call is already existing, do not proceed further to avoid
1829 * disabling/enabling both RX and TX devices, CSD calls, etc.
1830 * Once the voice call done, the HDMI channels can be configured to
1831 * max channels of remaining use cases.
1832 */
1833 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001834 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001835 __func__);
1836 ret = false;
1837 break;
1838 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001839 if (!enable_passthru) {
1840 ALOGV("%s: multi channel playback is active, "
1841 "no change in HDMI channels", __func__);
1842 ret = false;
1843 break;
1844 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001845 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001846 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001847 if (!enable_passthru) {
1848 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1849 ", no change in HDMI channels", __func__,
1850 usecase->stream.out->channel_mask);
1851 ret = false;
1852 break;
1853 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001854 }
1855 }
1856 }
Mingming Yin21854652016-04-13 11:54:02 -07001857 ALOGV("allow hdmi config %d", ret);
1858exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001859 return ret;
1860}
1861
Mingming Yin21854652016-04-13 11:54:02 -07001862static int check_and_set_hdmi_config(struct audio_device *adev,
1863 uint32_t channels,
1864 uint32_t sample_rate,
1865 audio_format_t format,
1866 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001867{
1868 struct listnode *node;
1869 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001870 int32_t factor = 1;
1871 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001872
Mingming Yin21854652016-04-13 11:54:02 -07001873 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1874 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001875
Mingming Yin21854652016-04-13 11:54:02 -07001876 if (channels != adev->cur_hdmi_channels) {
1877 ALOGV("channel does not match current hdmi channels");
1878 config = true;
1879 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001880
Mingming Yin21854652016-04-13 11:54:02 -07001881 if (sample_rate != adev->cur_hdmi_sample_rate) {
1882 ALOGV("sample rate does not match current hdmi sample rate");
1883 config = true;
1884 }
1885
1886 if (format != adev->cur_hdmi_format) {
1887 ALOGV("format does not match current hdmi format");
1888 config = true;
1889 }
1890
1891 /* TBD - add check for bit width */
1892 if (!config) {
1893 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001894 return 0;
1895 }
1896
Mingming Yin21854652016-04-13 11:54:02 -07001897 if (enable_passthru &&
1898 (format == AUDIO_FORMAT_E_AC3)) {
1899 ALOGV("factor 4 for E_AC3 passthru");
1900 factor = 4;
1901 }
1902
1903 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1904 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001905 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001906 adev->cur_hdmi_format = format;
1907 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001908
1909 /*
1910 * Deroute all the playback streams routed to HDMI so that
1911 * the back end is deactivated. Note that backend will not
1912 * be deactivated if any one stream is connected to it.
1913 */
1914 list_for_each(node, &adev->usecase_list) {
1915 usecase = node_to_item(node, struct audio_usecase, list);
1916 if (usecase->type == PCM_PLAYBACK &&
1917 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001918 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001919 }
1920 }
1921
Mingming Yin21854652016-04-13 11:54:02 -07001922 bool was_active = audio_extn_keep_alive_is_active();
1923 if (was_active)
1924 audio_extn_keep_alive_stop();
1925
Eric Laurent07eeafd2013-10-06 12:52:49 -07001926 /*
1927 * Enable all the streams disabled above. Now the HDMI backend
1928 * will be activated with new channel configuration
1929 */
1930 list_for_each(node, &adev->usecase_list) {
1931 usecase = node_to_item(node, struct audio_usecase, list);
1932 if (usecase->type == PCM_PLAYBACK &&
1933 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001934 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001935 }
1936 }
1937
Mingming Yin21854652016-04-13 11:54:02 -07001938 if (was_active)
1939 audio_extn_keep_alive_start();
1940
Eric Laurent07eeafd2013-10-06 12:52:49 -07001941 return 0;
1942}
1943
Mingming Yin21854652016-04-13 11:54:02 -07001944/* called with out lock taken */
1945static int check_and_set_hdmi_backend(struct stream_out *out)
1946{
1947 struct audio_device *adev = out->dev;
1948 int ret;
1949 bool enable_passthru = false;
1950
1951 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1952 return -1;
1953
1954 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1955
1956 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301957 audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07001958 enable_passthru = true;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301959 ALOGV("%s : enable_passthru is set to true", __func__);
Mingming Yin21854652016-04-13 11:54:02 -07001960 }
1961
1962 /* Check if change in HDMI channel config is allowed */
1963 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1964 return -EPERM;
1965 }
1966
1967 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1968 uint32_t channels;
1969 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1970
1971 if (enable_passthru) {
1972 audio_extn_passthru_on_start(out);
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301973 audio_extn_passthru_update_stream_configuration(adev, out);
Mingming Yin21854652016-04-13 11:54:02 -07001974 }
1975
1976 /* For pass through case, the backend should be configured as stereo */
1977 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1978 out->compr_config.codec->ch_in;
1979
1980 ret = check_and_set_hdmi_config(adev, channels,
1981 out->sample_rate, out->format,
1982 enable_passthru);
1983 } else
1984 ret = check_and_set_hdmi_config(adev, out->config.channels,
1985 out->config.rate,
1986 out->format,
1987 false);
1988 return ret;
1989}
1990
1991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992static int stop_output_stream(struct stream_out *out)
1993{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301994 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995 struct audio_usecase *uc_info;
1996 struct audio_device *adev = out->dev;
1997
Eric Laurent994a6932013-07-17 11:51:42 -07001998 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001999 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 uc_info = get_usecase_from_list(adev, out->usecase);
2001 if (uc_info == NULL) {
2002 ALOGE("%s: Could not find the usecase (%d) in the list",
2003 __func__, out->usecase);
2004 return -EINVAL;
2005 }
2006
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002007 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302008 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002009 if (adev->visualizer_stop_output != NULL)
2010 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002011
2012 audio_extn_dts_remove_state_notifier_node(out->usecase);
2013
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002014 if (adev->offload_effects_stop_output != NULL)
2015 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2016 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002017
Eric Laurent150dbfe2013-02-27 14:31:02 -08002018 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002019 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002020
2021 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002022 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002024 list_remove(&uc_info->list);
2025 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002027 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302028 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002029 ALOGV("Disable passthrough , reset mixer to pcm");
2030 /* NO_PASSTHROUGH */
2031 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002032
Mingming Yin21854652016-04-13 11:54:02 -07002033 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002034 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2035 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002036
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302037 /* Must be called after removing the usecase from list */
2038 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2039 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
2040 DEFAULT_HDMI_OUT_SAMPLE_RATE,
2041 DEFAULT_HDMI_OUT_FORMAT,
2042 false);
Eric Laurent994a6932013-07-17 11:51:42 -07002043 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 return ret;
2045}
2046
2047int start_output_stream(struct stream_out *out)
2048{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050 struct audio_usecase *uc_info;
2051 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302052 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002054 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2055 ret = -EINVAL;
2056 goto error_config;
2057 }
2058
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302059 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2060 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2061 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302062
Naresh Tanniru80659832014-06-04 18:17:56 +05302063 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302064 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302065 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302066 goto error_config;
2067 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302068
Eric Laurentb23d5282013-05-14 15:27:20 -07002069 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070 if (out->pcm_device_id < 0) {
2071 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2072 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002073 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002074 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 }
2076
2077 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002078
2079 if (!uc_info) {
2080 ret = -ENOMEM;
2081 goto error_config;
2082 }
2083
Mingming Yin21854652016-04-13 11:54:02 -07002084 /* This must be called before adding this usecase to the list */
2085 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2086 /* This call can fail if compress pass thru is already active */
2087 check_and_set_hdmi_backend(out);
2088 }
2089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 uc_info->id = out->usecase;
2091 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002092 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002093 uc_info->devices = out->devices;
2094 uc_info->in_snd_device = SND_DEVICE_NONE;
2095 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002096 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302098 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2099 adev->perf_lock_opts,
2100 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002101 select_devices(adev, out->usecase);
2102
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002103 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2104 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002105 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002106 unsigned int flags = PCM_OUT;
2107 unsigned int pcm_open_retry_count = 0;
2108 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2109 flags |= PCM_MMAP | PCM_NOIRQ;
2110 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002111 } else if (out->realtime) {
2112 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002113 } else
2114 flags |= PCM_MONOTONIC;
2115
2116 while (1) {
2117 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2118 flags, &out->config);
2119 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2120 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2121 if (out->pcm != NULL) {
2122 pcm_close(out->pcm);
2123 out->pcm = NULL;
2124 }
2125 if (pcm_open_retry_count-- == 0) {
2126 ret = -EIO;
2127 goto error_open;
2128 }
2129 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2130 continue;
2131 }
2132 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002133 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002134
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002135 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2136 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002137
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002138 ALOGV("%s: pcm_prepare", __func__);
2139 if (pcm_is_ready(out->pcm)) {
2140 ret = pcm_prepare(out->pcm);
2141 if (ret < 0) {
2142 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2143 pcm_close(out->pcm);
2144 out->pcm = NULL;
2145 goto error_open;
2146 }
2147 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002148 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002149 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2150 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002152 out->compr = compress_open(adev->snd_card,
2153 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002154 COMPRESS_IN, &out->compr_config);
2155 if (out->compr && !is_compress_ready(out->compr)) {
2156 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2157 compress_close(out->compr);
2158 out->compr = NULL;
2159 ret = -EIO;
2160 goto error_open;
2161 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302162 /* compress_open sends params of the track, so reset the flag here */
2163 out->is_compr_metadata_avail = false;
2164
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002165 if (out->offload_callback)
2166 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002167
Fred Oh3f43e742015-03-04 18:42:34 -08002168 /* Since small bufs uses blocking writes, a write will be blocked
2169 for the default max poll time (20s) in the event of an SSR.
2170 Reduce the poll time to observe and deal with SSR faster.
2171 */
Ashish Jain5106d362016-05-11 19:23:33 +05302172 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002173 compress_set_max_poll_wait(out->compr, 1000);
2174 }
2175
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002176 audio_extn_dts_create_state_notifier_node(out->usecase);
2177 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2178 popcount(out->channel_mask),
2179 out->playback_started);
2180
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002181#ifdef DS1_DOLBY_DDP_ENABLED
2182 if (audio_extn_is_dolby_format(out->format))
2183 audio_extn_dolby_send_ddp_endp_params(adev);
2184#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302185 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002186 if (adev->visualizer_start_output != NULL)
2187 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2188 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302189 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002190 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002191 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002193
2194 if (ret == 0) {
2195 register_out_stream(out);
2196 if (out->realtime) {
2197 ret = pcm_start(out->pcm);
2198 if (ret < 0)
2199 goto error_open;
2200 }
2201 }
2202
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302203 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002204 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002205
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002206 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302208 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002210error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302211 /*
2212 * sleep 50ms to allow sufficient time for kernel
2213 * drivers to recover incases like SSR.
2214 */
2215 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002216 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217}
2218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219static int check_input_parameters(uint32_t sample_rate,
2220 audio_format_t format,
2221 int channel_count)
2222{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002223 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302225 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2226 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2227 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002228 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302229 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002230
2231 switch (channel_count) {
2232 case 1:
2233 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302234 case 3:
2235 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002236 case 6:
2237 break;
2238 default:
2239 ret = -EINVAL;
2240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241
2242 switch (sample_rate) {
2243 case 8000:
2244 case 11025:
2245 case 12000:
2246 case 16000:
2247 case 22050:
2248 case 24000:
2249 case 32000:
2250 case 44100:
2251 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302252 case 96000:
2253 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 break;
2255 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002256 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 }
2258
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002259 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260}
2261
2262static size_t get_input_buffer_size(uint32_t sample_rate,
2263 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002264 int channel_count,
2265 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266{
2267 size_t size = 0;
2268
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002269 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2270 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002272 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002273 if (is_low_latency)
2274 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302275
2276 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002278 /* make sure the size is multiple of 32 bytes
2279 * At 48 kHz mono 16-bit PCM:
2280 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2281 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2282 */
2283 size += 0x1f;
2284 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002285
2286 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287}
2288
Ashish Jain5106d362016-05-11 19:23:33 +05302289static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2290{
2291 uint64_t actual_frames_rendered = 0;
2292 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2293
2294 /* This adjustment accounts for buffering after app processor.
2295 * It is based on estimated DSP latency per use case, rather than exact.
2296 */
2297 int64_t platform_latency = platform_render_latency(out->usecase) *
2298 out->sample_rate / 1000000LL;
2299
2300 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2301 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2302 * hence only estimate.
2303 */
2304 int64_t signed_frames = out->written - kernel_buffer_size;
2305
2306 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2307
2308 if (signed_frames > 0)
2309 actual_frames_rendered = signed_frames;
2310
2311 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2312 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2313 (long long int)out->written, (int)kernel_buffer_size,
2314 audio_bytes_per_sample(out->compr_config.codec->format),
2315 popcount(out->channel_mask));
2316
2317 return actual_frames_rendered;
2318}
2319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2321{
2322 struct stream_out *out = (struct stream_out *)stream;
2323
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002324 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325}
2326
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002327static int out_set_sample_rate(struct audio_stream *stream __unused,
2328 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329{
2330 return -ENOSYS;
2331}
2332
2333static size_t out_get_buffer_size(const struct audio_stream *stream)
2334{
2335 struct stream_out *out = (struct stream_out *)stream;
2336
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002337 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002339 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2340 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302341 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302342 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002344 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002345 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
2348static uint32_t out_get_channels(const struct audio_stream *stream)
2349{
2350 struct stream_out *out = (struct stream_out *)stream;
2351
2352 return out->channel_mask;
2353}
2354
2355static audio_format_t out_get_format(const struct audio_stream *stream)
2356{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 struct stream_out *out = (struct stream_out *)stream;
2358
2359 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360}
2361
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002362static int out_set_format(struct audio_stream *stream __unused,
2363 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364{
2365 return -ENOSYS;
2366}
2367
2368static int out_standby(struct audio_stream *stream)
2369{
2370 struct stream_out *out = (struct stream_out *)stream;
2371 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002372
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302373 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2374 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002376 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002378 if (adev->adm_deregister_stream)
2379 adev->adm_deregister_stream(adev->adm_data, out->handle);
2380
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002381 if (is_offload_usecase(out->usecase))
2382 stop_compressed_output_l(out);
2383
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002384 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002386 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2387 voice_extn_compress_voip_close_output_stream(stream);
2388 pthread_mutex_unlock(&adev->lock);
2389 pthread_mutex_unlock(&out->lock);
2390 ALOGD("VOIP output entered standby");
2391 return 0;
2392 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 if (out->pcm) {
2394 pcm_close(out->pcm);
2395 out->pcm = NULL;
2396 }
2397 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002398 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302399 out->send_next_track_params = false;
2400 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002401 out->gapless_mdata.encoder_delay = 0;
2402 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 if (out->compr != NULL) {
2404 compress_close(out->compr);
2405 out->compr = NULL;
2406 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002409 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410 }
2411 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302412 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413 return 0;
2414}
2415
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002416static int out_dump(const struct audio_stream *stream __unused,
2417 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418{
2419 return 0;
2420}
2421
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002422static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2423{
2424 int ret = 0;
2425 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002426
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002427 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002428 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002429 return -EINVAL;
2430 }
2431
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302432 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002433
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002434 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2435 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302436 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002437 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002438 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2439 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302440 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002441 }
2442
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002443 ALOGV("%s new encoder delay %u and padding %u", __func__,
2444 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2445
2446 return 0;
2447}
2448
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002449static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2450{
2451 return out == adev->primary_output || out == adev->voice_tx_output;
2452}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2455{
2456 struct stream_out *out = (struct stream_out *)stream;
2457 struct audio_device *adev = out->dev;
2458 struct str_parms *parms;
2459 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002460 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461
sangwoobc677242013-08-08 16:53:43 +09002462 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002463 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302465 if (!parms)
2466 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002467 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2468 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002470 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002471 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002473 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002474 * When HDMI cable is unplugged the music playback is paused and
2475 * the policy manager sends routing=0. But the audioflinger continues
2476 * to write data until standby time (3sec). As the HDMI core is
2477 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002478 * Avoid this by routing audio to speaker until standby.
2479 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002480 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2481 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302482 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002483 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2484 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002485 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302486 /*
2487 * When A2DP is disconnected the
2488 * music playback is paused and the policy manager sends routing=0
2489 * But the audioflingercontinues to write data until standby time
2490 * (3sec). As BT is turned off, the write gets blocked.
2491 * Avoid this by routing audio to speaker until standby.
2492 */
2493 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2494 (val == AUDIO_DEVICE_NONE)) {
2495 val = AUDIO_DEVICE_OUT_SPEAKER;
2496 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002497
2498 /*
2499 * select_devices() call below switches all the usecases on the same
2500 * backend to the new device. Refer to check_usecases_codec_backend() in
2501 * the select_devices(). But how do we undo this?
2502 *
2503 * For example, music playback is active on headset (deep-buffer usecase)
2504 * and if we go to ringtones and select a ringtone, low-latency usecase
2505 * will be started on headset+speaker. As we can't enable headset+speaker
2506 * and headset devices at the same time, select_devices() switches the music
2507 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2508 * So when the ringtone playback is completed, how do we undo the same?
2509 *
2510 * We are relying on the out_set_parameters() call on deep-buffer output,
2511 * once the ringtone playback is ended.
2512 * NOTE: We should not check if the current devices are same as new devices.
2513 * Because select_devices() must be called to switch back the music
2514 * playback to headset.
2515 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002516 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002517 audio_devices_t new_dev = val;
2518 bool same_dev = out->devices == new_dev;
2519 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002520
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002521 if (output_drives_call(adev, out)) {
2522 if(!voice_is_in_call(adev)) {
2523 if (adev->mode == AUDIO_MODE_IN_CALL) {
2524 adev->current_call_output = out;
2525 ret = voice_start_call(adev);
2526 }
2527 } else {
2528 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002529 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002530 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002531 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002532
2533 if (!out->standby) {
2534 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2535 adev->perf_lock_opts,
2536 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002537 if (!same_dev) {
2538 ALOGV("update routing change");
2539 out->routing_change = true;
2540 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002541 select_devices(adev, out->usecase);
2542 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2543 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002544 }
2545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002547 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002549
2550 if (out == adev->primary_output) {
2551 pthread_mutex_lock(&adev->lock);
2552 audio_extn_set_parameters(adev, parms);
2553 pthread_mutex_unlock(&adev->lock);
2554 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002555 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002556 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002557 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002558
2559 audio_extn_dts_create_state_notifier_node(out->usecase);
2560 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2561 popcount(out->channel_mask),
2562 out->playback_started);
2563
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002564 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002565 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302568error:
Eric Laurent994a6932013-07-17 11:51:42 -07002569 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 return ret;
2571}
2572
2573static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2574{
2575 struct stream_out *out = (struct stream_out *)stream;
2576 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002577 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 char value[256];
2579 struct str_parms *reply = str_parms_create();
2580 size_t i, j;
2581 int ret;
2582 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002583
2584 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002585 if (reply) {
2586 str_parms_destroy(reply);
2587 }
2588 if (query) {
2589 str_parms_destroy(query);
2590 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002591 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2592 return NULL;
2593 }
2594
Eric Laurent994a6932013-07-17 11:51:42 -07002595 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2597 if (ret >= 0) {
2598 value[0] = '\0';
2599 i = 0;
2600 while (out->supported_channel_masks[i] != 0) {
2601 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2602 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2603 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002604 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002606 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 first = false;
2608 break;
2609 }
2610 }
2611 i++;
2612 }
2613 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2614 str = str_parms_to_str(reply);
2615 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002616 voice_extn_out_get_parameters(out, query, reply);
2617 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002618 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002619 free(str);
2620 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002623
Alexy Joseph62142aa2015-11-16 15:10:34 -08002624
2625 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2626 if (ret >= 0) {
2627 value[0] = '\0';
2628 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2629 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302630 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002631 } else {
2632 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302633 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002634 }
2635 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002636 if (str)
2637 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002638 str = str_parms_to_str(reply);
2639 }
2640
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002641 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2642 if (ret >= 0) {
2643 value[0] = '\0';
2644 i = 0;
2645 first = true;
2646 while (out->supported_formats[i] != 0) {
2647 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2648 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2649 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002650 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002651 }
2652 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2653 first = false;
2654 break;
2655 }
2656 }
2657 i++;
2658 }
2659 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002660 if (str)
2661 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002662 str = str_parms_to_str(reply);
2663 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002664
2665 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2666 if (ret >= 0) {
2667 value[0] = '\0';
2668 i = 0;
2669 first = true;
2670 while (out->supported_sample_rates[i] != 0) {
2671 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2672 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2673 if (!first) {
2674 strlcat(value, "|", sizeof(value));
2675 }
2676 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2677 first = false;
2678 break;
2679 }
2680 }
2681 i++;
2682 }
2683 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2684 if (str)
2685 free(str);
2686 str = str_parms_to_str(reply);
2687 }
2688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 str_parms_destroy(query);
2690 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002691 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 return str;
2693}
2694
2695static uint32_t out_get_latency(const struct audio_stream_out *stream)
2696{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002697 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002699 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700
Alexy Josephaa54c872014-12-03 02:46:47 -08002701 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002702 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002703 } else if (out->realtime) {
2704 // since the buffer won't be filled up faster than realtime,
2705 // return a smaller number
2706 if (out->config.rate)
2707 period_ms = (out->af_period_multiplier * out->config.period_size *
2708 1000) / (out->config.rate);
2709 else
2710 period_ms = 0;
2711 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002712 } else {
2713 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002714 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002715 }
2716
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302717 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002718 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719}
2720
2721static int out_set_volume(struct audio_stream_out *stream, float left,
2722 float right)
2723{
Eric Laurenta9024de2013-04-04 09:19:12 -07002724 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002725 int volume[2];
2726
Eric Laurenta9024de2013-04-04 09:19:12 -07002727 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2728 /* only take left channel into account: the API is for stereo anyway */
2729 out->muted = (left == 0.0f);
2730 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002731 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302732 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002733 /*
2734 * Set mute or umute on HDMI passthrough stream.
2735 * Only take left channel into account.
2736 * Mute is 0 and unmute 1
2737 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302738 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002739 } else {
2740 char mixer_ctl_name[128];
2741 struct audio_device *adev = out->dev;
2742 struct mixer_ctl *ctl;
2743 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002744 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002745
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002746 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2747 "Compress Playback %d Volume", pcm_device_id);
2748 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2749 if (!ctl) {
2750 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2751 __func__, mixer_ctl_name);
2752 return -EINVAL;
2753 }
2754 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2755 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2756 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2757 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002759 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 return -ENOSYS;
2762}
2763
2764static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2765 size_t bytes)
2766{
2767 struct stream_out *out = (struct stream_out *)stream;
2768 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302769 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002770 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002772 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302773
Naresh Tanniru80659832014-06-04 18:17:56 +05302774 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002775
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302776 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302777 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302778 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2779 pthread_mutex_unlock(&out->lock);
2780 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302781 } else {
2782 /* increase written size during SSR to avoid mismatch
2783 * with the written frames count in AF
2784 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302785 if (audio_bytes_per_sample(out->format) != 0)
2786 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302787 ALOGD(" %s: sound card is not active/SSR state", __func__);
2788 ret= -EIO;
2789 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302790 }
2791 }
2792
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302793 if (audio_extn_passthru_should_drop_data(out)) {
2794 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2795 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2796 out_get_sample_rate(&out->stream.common));
2797 goto exit;
2798 }
2799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002800 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002801 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002802 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002803 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2804 ret = voice_extn_compress_voip_start_output_stream(out);
2805 else
2806 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002807 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002810 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 goto exit;
2812 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002813
2814 if (last_known_cal_step != -1) {
2815 ALOGD("%s: retry previous failed cal level set", __func__);
2816 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2817 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819
Ashish Jain81eb2a82015-05-13 10:52:34 +05302820 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002821 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302822 adev->is_channel_status_set = true;
2823 }
2824
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002825 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002826 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002827 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002828 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002829 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2830 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302831 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2832 ALOGD("copl(%p):send next track params in gapless", out);
2833 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2834 out->send_next_track_params = false;
2835 out->is_compr_metadata_avail = false;
2836 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002837 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302838 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302839 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002840
Ashish Jain83a6cc22016-06-28 14:34:17 +05302841 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302842 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302843 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302844 pthread_mutex_unlock(&out->lock);
2845 return -EINVAL;
2846 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302847 audio_format_t dst_format = out->hal_op_format;
2848 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302849
2850 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2851 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2852
Ashish Jain83a6cc22016-06-28 14:34:17 +05302853 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302854 dst_format,
2855 buffer,
2856 src_format,
2857 frames);
2858
Ashish Jain83a6cc22016-06-28 14:34:17 +05302859 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302860 bytes_to_write);
2861
2862 /*Convert written bytes in audio flinger format*/
2863 if (ret > 0)
2864 ret = ((ret * format_to_bitwidth_table[out->format]) /
2865 format_to_bitwidth_table[dst_format]);
2866 }
2867 } else
2868 ret = compress_write(out->compr, buffer, bytes);
2869
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302870 if (ret < 0)
2871 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302872 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002873 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302874 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302876 } else if (-ENETRESET == ret) {
2877 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2878 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2879 pthread_mutex_unlock(&out->lock);
2880 out_standby(&out->stream.common);
2881 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 }
Ashish Jain5106d362016-05-11 19:23:33 +05302883 if ( ret == (ssize_t)bytes && !out->non_blocking)
2884 out->written += bytes;
2885
Naresh Tanniru80659832014-06-04 18:17:56 +05302886 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002888 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->playback_started = 1;
2890 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002891
2892 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2893 popcount(out->channel_mask),
2894 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002895 }
2896 pthread_mutex_unlock(&out->lock);
2897 return ret;
2898 } else {
2899 if (out->pcm) {
2900 if (out->muted)
2901 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002902
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302903 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002904
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002905 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002906
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002907 if (out->config.rate)
2908 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2909 out->config.rate;
2910
2911 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2912
2913 request_out_focus(out, ns);
2914
2915 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002916 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002917 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302918 out->convert_buffer != NULL) {
2919
2920 memcpy_by_audio_format(out->convert_buffer,
2921 out->hal_op_format,
2922 buffer,
2923 out->hal_ip_format,
2924 out->config.period_size * out->config.channels);
2925
2926 ret = pcm_write(out->pcm, out->convert_buffer,
2927 (out->config.period_size *
2928 out->config.channels *
2929 format_to_bitwidth_table[out->hal_op_format]));
2930 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002931 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302932 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002933
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002934 release_out_focus(out);
2935
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302936 if (ret < 0)
2937 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302938 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2939 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2940 else
2941 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002942 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 }
2944
2945exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302946 /* ToDo: There may be a corner case when SSR happens back to back during
2947 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302948 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302949 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302950 }
2951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952 pthread_mutex_unlock(&out->lock);
2953
2954 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002955 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002956 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302957 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302958 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302959 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302960 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302961 out->standby = true;
2962 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302964 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302965 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 }
2967 return bytes;
2968}
2969
2970static int out_get_render_position(const struct audio_stream_out *stream,
2971 uint32_t *dsp_frames)
2972{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002973 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302974 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002975
2976 if (dsp_frames == NULL)
2977 return -EINVAL;
2978
2979 *dsp_frames = 0;
2980 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002981 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302982
2983 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2984 * this operation and adev_close_output_stream(where out gets reset).
2985 */
2986 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2987 *dsp_frames = get_actual_pcm_frames_rendered(out);
2988 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2989 return 0;
2990 }
2991
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002992 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302993 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302994 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002995 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302996 if (ret < 0)
2997 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302999 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 }
3001 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303002 if (-ENETRESET == ret) {
3003 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3004 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3005 return -EINVAL;
3006 } else if(ret < 0) {
3007 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3008 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303009 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3010 /*
3011 * Handle corner case where compress session is closed during SSR
3012 * and timestamp is queried
3013 */
3014 ALOGE(" ERROR: sound card not active, return error");
3015 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303016 } else {
3017 return 0;
3018 }
Zhou Song32a556e2015-05-05 10:46:56 +08003019 } else if (audio_is_linear_pcm(out->format)) {
3020 *dsp_frames = out->written;
3021 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 } else
3023 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024}
3025
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003026static int out_add_audio_effect(const struct audio_stream *stream __unused,
3027 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028{
3029 return 0;
3030}
3031
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003032static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3033 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
3035 return 0;
3036}
3037
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003038static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3039 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040{
3041 return -EINVAL;
3042}
3043
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003044static int out_get_presentation_position(const struct audio_stream_out *stream,
3045 uint64_t *frames, struct timespec *timestamp)
3046{
3047 struct stream_out *out = (struct stream_out *)stream;
3048 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003049 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003050
Ashish Jain5106d362016-05-11 19:23:33 +05303051 /* below piece of code is not guarded against any lock because audioFliner serializes
3052 * this operation and adev_close_output_stream( where out gets reset).
3053 */
3054 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3055 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3056 *frames = get_actual_pcm_frames_rendered(out);
3057 /* this is the best we can do */
3058 clock_gettime(CLOCK_MONOTONIC, timestamp);
3059 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3060 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3061 return 0;
3062 }
3063
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003064 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003065
Ashish Jain5106d362016-05-11 19:23:33 +05303066 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3067 ret = compress_get_tstamp(out->compr, &dsp_frames,
3068 &out->sample_rate);
3069 ALOGVV("%s rendered frames %ld sample_rate %d",
3070 __func__, dsp_frames, out->sample_rate);
3071 *frames = dsp_frames;
3072 if (ret < 0)
3073 ret = -errno;
3074 if (-ENETRESET == ret) {
3075 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3076 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3077 ret = -EINVAL;
3078 } else
3079 ret = 0;
3080 /* this is the best we can do */
3081 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003082 } else {
3083 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003084 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003085 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3086 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003087 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003088 // This adjustment accounts for buffering after app processor.
3089 // It is based on estimated DSP latency per use case, rather than exact.
3090 signed_frames -=
3091 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3092
Eric Laurent949a0892013-09-20 09:20:13 -07003093 // It would be unusual for this value to be negative, but check just in case ...
3094 if (signed_frames >= 0) {
3095 *frames = signed_frames;
3096 ret = 0;
3097 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003098 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303099 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3100 *frames = out->written;
3101 clock_gettime(CLOCK_MONOTONIC, timestamp);
3102 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003103 }
3104 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003105 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003106 return ret;
3107}
3108
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003109static int out_set_callback(struct audio_stream_out *stream,
3110 stream_callback_t callback, void *cookie)
3111{
3112 struct stream_out *out = (struct stream_out *)stream;
3113
3114 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003115 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003116 out->offload_callback = callback;
3117 out->offload_cookie = cookie;
3118 pthread_mutex_unlock(&out->lock);
3119 return 0;
3120}
3121
3122static int out_pause(struct audio_stream_out* stream)
3123{
3124 struct stream_out *out = (struct stream_out *)stream;
3125 int status = -ENOSYS;
3126 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003127 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003128 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003129 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003130 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303131 struct audio_device *adev = out->dev;
3132 int snd_scard_state = get_snd_card_state(adev);
3133
3134 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3135 status = compress_pause(out->compr);
3136
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003137 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003138
Mingming Yin21854652016-04-13 11:54:02 -07003139 if (audio_extn_passthru_is_active()) {
3140 ALOGV("offload use case, pause passthru");
3141 audio_extn_passthru_on_pause(out);
3142 }
3143
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303144 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003145 audio_extn_dts_notify_playback_state(out->usecase, 0,
3146 out->sample_rate, popcount(out->channel_mask),
3147 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 }
3149 pthread_mutex_unlock(&out->lock);
3150 }
3151 return status;
3152}
3153
3154static int out_resume(struct audio_stream_out* stream)
3155{
3156 struct stream_out *out = (struct stream_out *)stream;
3157 int status = -ENOSYS;
3158 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003159 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003160 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003161 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003162 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003163 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303164 struct audio_device *adev = out->dev;
3165 int snd_scard_state = get_snd_card_state(adev);
3166
Mingming Yin21854652016-04-13 11:54:02 -07003167 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3168 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3169 pthread_mutex_lock(&out->dev->lock);
3170 ALOGV("offload resume, check and set hdmi backend again");
3171 check_and_set_hdmi_backend(out);
3172 pthread_mutex_unlock(&out->dev->lock);
3173 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303174 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003175 }
3176 if (!status) {
3177 out->offload_state = OFFLOAD_STATE_PLAYING;
3178 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303179 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003180 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3181 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003182 }
3183 pthread_mutex_unlock(&out->lock);
3184 }
3185 return status;
3186}
3187
3188static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3189{
3190 struct stream_out *out = (struct stream_out *)stream;
3191 int status = -ENOSYS;
3192 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003193 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003194 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003195 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3196 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3197 else
3198 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3199 pthread_mutex_unlock(&out->lock);
3200 }
3201 return status;
3202}
3203
3204static int out_flush(struct audio_stream_out* stream)
3205{
3206 struct stream_out *out = (struct stream_out *)stream;
3207 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003208 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003209 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003210 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303212 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003213 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003214 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215 return 0;
3216 }
3217 return -ENOSYS;
3218}
3219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220/** audio_stream_in implementation **/
3221static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3222{
3223 struct stream_in *in = (struct stream_in *)stream;
3224
3225 return in->config.rate;
3226}
3227
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003228static int in_set_sample_rate(struct audio_stream *stream __unused,
3229 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230{
3231 return -ENOSYS;
3232}
3233
3234static size_t in_get_buffer_size(const struct audio_stream *stream)
3235{
3236 struct stream_in *in = (struct stream_in *)stream;
3237
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003238 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3239 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003240 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3241 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003242
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003243 return in->config.period_size * in->af_period_multiplier *
3244 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245}
3246
3247static uint32_t in_get_channels(const struct audio_stream *stream)
3248{
3249 struct stream_in *in = (struct stream_in *)stream;
3250
3251 return in->channel_mask;
3252}
3253
3254static audio_format_t in_get_format(const struct audio_stream *stream)
3255{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003256 struct stream_in *in = (struct stream_in *)stream;
3257
3258 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259}
3260
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003261static int in_set_format(struct audio_stream *stream __unused,
3262 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263{
3264 return -ENOSYS;
3265}
3266
3267static int in_standby(struct audio_stream *stream)
3268{
3269 struct stream_in *in = (struct stream_in *)stream;
3270 struct audio_device *adev = in->dev;
3271 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303272 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3273 stream, in->usecase, use_case_table[in->usecase]);
3274
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003275 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003276 if (!in->standby && in->is_st_session) {
3277 ALOGD("%s: sound trigger pcm stop lab", __func__);
3278 audio_extn_sound_trigger_stop_lab(in);
3279 in->standby = 1;
3280 }
3281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003283 if (adev->adm_deregister_stream)
3284 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3285
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003286 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003288 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3289 voice_extn_compress_voip_close_input_stream(stream);
3290 ALOGD("VOIP input entered standby");
3291 } else {
3292 if (in->pcm) {
3293 pcm_close(in->pcm);
3294 in->pcm = NULL;
3295 }
3296 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003297 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003298 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299 }
3300 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003301 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302 return status;
3303}
3304
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003305static int in_dump(const struct audio_stream *stream __unused,
3306 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307{
3308 return 0;
3309}
3310
3311static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3312{
3313 struct stream_in *in = (struct stream_in *)stream;
3314 struct audio_device *adev = in->dev;
3315 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003317 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303319 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 parms = str_parms_create_str(kvpairs);
3321
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303322 if (!parms)
3323 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003324 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003325 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003326
3327 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3328 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 val = atoi(value);
3330 /* no audio source uses val == 0 */
3331 if ((in->source != val) && (val != 0)) {
3332 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003333 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3334 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3335 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003336 (in->config.rate == 8000 || in->config.rate == 16000 ||
3337 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003338 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003339 err = voice_extn_compress_voip_open_input_stream(in);
3340 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003341 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003342 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003343 }
3344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 }
3346 }
3347
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003348 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3349 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003351 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 in->device = val;
3353 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003354 if (!in->standby && !in->is_st_session) {
3355 ALOGV("update input routing change");
3356 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003357 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003358 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 }
3360 }
3361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003363 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364
3365 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303366error:
Eric Laurent994a6932013-07-17 11:51:42 -07003367 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 return ret;
3369}
3370
3371static char* in_get_parameters(const struct audio_stream *stream,
3372 const char *keys)
3373{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003374 struct stream_in *in = (struct stream_in *)stream;
3375 struct str_parms *query = str_parms_create_str(keys);
3376 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003377 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003378
3379 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003380 if (reply) {
3381 str_parms_destroy(reply);
3382 }
3383 if (query) {
3384 str_parms_destroy(query);
3385 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003386 ALOGE("in_get_parameters: failed to create query or reply");
3387 return NULL;
3388 }
3389
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003390 ALOGV("%s: enter: keys - %s", __func__, keys);
3391
3392 voice_extn_in_get_parameters(in, query, reply);
3393
3394 str = str_parms_to_str(reply);
3395 str_parms_destroy(query);
3396 str_parms_destroy(reply);
3397
3398 ALOGV("%s: exit: returns - %s", __func__, str);
3399 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400}
3401
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003402static int in_set_gain(struct audio_stream_in *stream __unused,
3403 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404{
3405 return 0;
3406}
3407
3408static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3409 size_t bytes)
3410{
3411 struct stream_in *in = (struct stream_in *)stream;
3412 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303413 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303414 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303415 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003417 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303418
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003419 if (in->is_st_session) {
3420 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3421 /* Read from sound trigger HAL */
3422 audio_extn_sound_trigger_read(in, buffer, bytes);
3423 pthread_mutex_unlock(&in->lock);
3424 return bytes;
3425 }
3426
Ashish Jainbbce4322016-02-16 13:25:27 +05303427 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003428 ALOGD(" %s: sound card is not active/SSR state", __func__);
3429 ret= -EIO;;
3430 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303431 }
3432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003434 pthread_mutex_lock(&adev->lock);
3435 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3436 ret = voice_extn_compress_voip_start_input_stream(in);
3437 else
3438 ret = start_input_stream(in);
3439 pthread_mutex_unlock(&adev->lock);
3440 if (ret != 0) {
3441 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003442 }
3443 in->standby = 0;
3444 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003446 // what's the duration requested by the client?
3447 long ns = 0;
3448
3449 if (in->config.rate)
3450 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3451 in->config.rate;
3452
3453 request_in_focus(in, ns);
3454 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303457 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003458 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303459 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003460 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003461 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003462 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303463 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003464 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303465 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3466 if (bytes % 4 == 0) {
3467 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3468 int_buf_stream = buffer;
3469 for (size_t itt=0; itt < bytes/4 ; itt++) {
3470 int_buf_stream[itt] >>= 8;
3471 }
3472 } else {
3473 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3474 ret = -EINVAL;
3475 goto exit;
3476 }
3477 } if (ret < 0) {
3478 ret = -errno;
3479 }
3480 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 }
3482
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003483 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 /*
3486 * Instead of writing zeroes here, we could trust the hardware
3487 * to always provide zeroes when muted.
3488 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303489 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3490 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 memset(buffer, 0, bytes);
3492
3493exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303494 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303495 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003496 if (-ENETRESET == ret)
3497 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 pthread_mutex_unlock(&in->lock);
3500
3501 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303502 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303503 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303504 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303505 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303506 in->standby = true;
3507 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303508 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003510 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303511 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303512 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 }
3514 return bytes;
3515}
3516
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003517static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518{
3519 return 0;
3520}
3521
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003522static int add_remove_audio_effect(const struct audio_stream *stream,
3523 effect_handle_t effect,
3524 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003526 struct stream_in *in = (struct stream_in *)stream;
3527 int status = 0;
3528 effect_descriptor_t desc;
3529
3530 status = (*effect)->get_descriptor(effect, &desc);
3531 if (status != 0)
3532 return status;
3533
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003534 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003535 pthread_mutex_lock(&in->dev->lock);
3536 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3537 in->enable_aec != enable &&
3538 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3539 in->enable_aec = enable;
3540 if (!in->standby)
3541 select_devices(in->dev, in->usecase);
3542 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003543 if (in->enable_ns != enable &&
3544 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3545 in->enable_ns = enable;
3546 if (!in->standby)
3547 select_devices(in->dev, in->usecase);
3548 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003549 pthread_mutex_unlock(&in->dev->lock);
3550 pthread_mutex_unlock(&in->lock);
3551
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552 return 0;
3553}
3554
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003555static int in_add_audio_effect(const struct audio_stream *stream,
3556 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557{
Eric Laurent994a6932013-07-17 11:51:42 -07003558 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003559 return add_remove_audio_effect(stream, effect, true);
3560}
3561
3562static int in_remove_audio_effect(const struct audio_stream *stream,
3563 effect_handle_t effect)
3564{
Eric Laurent994a6932013-07-17 11:51:42 -07003565 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003566 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567}
3568
3569static int adev_open_output_stream(struct audio_hw_device *dev,
3570 audio_io_handle_t handle,
3571 audio_devices_t devices,
3572 audio_output_flags_t flags,
3573 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003574 struct audio_stream_out **stream_out,
3575 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576{
3577 struct audio_device *adev = (struct audio_device *)dev;
3578 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303579 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003580 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303583
3584 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3585 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003586 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303587 return -EINVAL;
3588 }
3589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3591
Mingming Yin3a941d42016-02-17 18:08:05 -08003592 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3593 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303594 devices, flags, &out->stream);
3595
3596
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003597 if (!out) {
3598 return -ENOMEM;
3599 }
3600
Haynes Mathew George204045b2015-02-25 20:32:03 -08003601 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003602 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003603 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 if (devices == AUDIO_DEVICE_NONE)
3606 devices = AUDIO_DEVICE_OUT_SPEAKER;
3607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 out->flags = flags;
3609 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003610 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003611 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003612 out->sample_rate = config->sample_rate;
3613 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3614 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003615 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003616 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003617 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303618 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619
Mingming Yin3a941d42016-02-17 18:08:05 -08003620 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3621 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3622 pthread_mutex_lock(&adev->lock);
3623 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3624 ret = read_hdmi_sink_caps(out);
3625 pthread_mutex_unlock(&adev->lock);
3626 if (ret != 0) {
3627 if (ret == -ENOSYS) {
3628 /* ignore and go with default */
3629 ret = 0;
3630 } else {
3631 ALOGE("error reading hdmi sink caps");
3632 goto error_open;
3633 }
3634 }
3635 }
3636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003638 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303639 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3640 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003641 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3642 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3643
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003644 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003645 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3646 /*
3647 * Do not handle stereo output in Multi-channel cases
3648 * Stereo case is handled in normal playback path
3649 */
3650 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3651 ret = AUDIO_CHANNEL_OUT_STEREO;
3652 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003653
3654 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3655 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003656 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003657 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003658 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003659
3660 if (config->sample_rate == 0)
3661 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3662 if (config->channel_mask == 0)
3663 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003664 if (config->format == 0)
3665 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003666
3667 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003668 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003669 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3671 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003673 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003675 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3676 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003677 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003678 ret = voice_extn_compress_voip_open_output_stream(out);
3679 if (ret != 0) {
3680 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3681 __func__, ret);
3682 goto error_open;
3683 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003684 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3685 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3686
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3688 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3689 ALOGE("%s: Unsupported Offload information", __func__);
3690 ret = -EINVAL;
3691 goto error_open;
3692 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003693
Mingming Yin3a941d42016-02-17 18:08:05 -08003694 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003695 if(config->offload_info.format == 0)
3696 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003697 if (config->offload_info.sample_rate == 0)
3698 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003699 }
3700
Mingming Yin90310102013-11-13 16:57:00 -08003701 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303702 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003703 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003704 ret = -EINVAL;
3705 goto error_open;
3706 }
3707
3708 out->compr_config.codec = (struct snd_codec *)
3709 calloc(1, sizeof(struct snd_codec));
3710
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003711 if (!out->compr_config.codec) {
3712 ret = -ENOMEM;
3713 goto error_open;
3714 }
3715
vivek mehta0ea887a2015-08-26 14:01:20 -07003716 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303717 out->stream.pause = out_pause;
3718 out->stream.flush = out_flush;
3719 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003720 out->usecase = get_offload_usecase(adev, true);
3721 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003722 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003723 out->stream.set_callback = out_set_callback;
3724 out->stream.pause = out_pause;
3725 out->stream.resume = out_resume;
3726 out->stream.drain = out_drain;
3727 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003728 out->usecase = get_offload_usecase(adev, false);
3729 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003730 }
vivek mehta446c3962015-09-14 10:57:35 -07003731
3732 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003733 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3734 config->format == 0 && config->sample_rate == 0 &&
3735 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003736 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003737 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3738 } else {
3739 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3740 ret = -EEXIST;
3741 goto error_open;
3742 }
vivek mehta446c3962015-09-14 10:57:35 -07003743 }
3744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003745 if (config->offload_info.channel_mask)
3746 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003747 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003748 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003749 config->offload_info.channel_mask = config->channel_mask;
3750 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003751 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003752 out->sample_rate = config->offload_info.sample_rate;
3753
Mingming Yin3ee55c62014-08-04 14:23:35 -07003754 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003755
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303756 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3757 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3758 audio_extn_dolby_send_ddp_endp_params(adev);
3759 audio_extn_dolby_set_dmid(adev);
3760 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003761
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003763 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003764 out->compr_config.codec->bit_rate =
3765 config->offload_info.bit_rate;
3766 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303767 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003768 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303769 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003770 /*TODO: Do we need to change it for passthrough */
3771 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003772
Manish Dewangana6fc5442015-08-24 20:30:31 +05303773 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3774 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3775 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3776 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303777
3778 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3779 AUDIO_FORMAT_PCM) {
3780
3781 /*Based on platform support, configure appropriate alsa format for corresponding
3782 *hal input format.
3783 */
3784 out->compr_config.codec->format = hal_format_to_alsa(
3785 config->offload_info.format);
3786
Ashish Jain83a6cc22016-06-28 14:34:17 +05303787 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303788 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303789 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303790
3791 /*for direct PCM playback populate bit_width based on selected alsa format as
3792 *hal input format and alsa format might differ based on platform support.
3793 */
3794 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303795 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303796
3797 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3798
3799 /* Check if alsa session is configured with the same format as HAL input format,
3800 * if not then derive correct fragment size needed to accomodate the
3801 * conversion of HAL input format to alsa format.
3802 */
3803 audio_extn_utils_update_direct_pcm_fragment_size(out);
3804
3805 /*if hal input and output fragment size is different this indicates HAL input format is
3806 *not same as the alsa format
3807 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303808 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303809 /*Allocate a buffer to convert input data to the alsa configured format.
3810 *size of convert buffer is equal to the size required to hold one fragment size
3811 *worth of pcm data, this is because flinger does not write more than fragment_size
3812 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303813 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3814 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303815 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3816 ret = -ENOMEM;
3817 goto error_open;
3818 }
3819 }
3820 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3821 out->compr_config.fragment_size =
3822 audio_extn_passthru_get_buffer_size(&config->offload_info);
3823 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3824 } else {
3825 out->compr_config.fragment_size =
3826 platform_get_compress_offload_buffer_size(&config->offload_info);
3827 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3828 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003829
Amit Shekhar6f461b12014-08-01 14:52:58 -07003830 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303831 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003832
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003833 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3834 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003835
Alexy Josephaa54c872014-12-03 02:46:47 -08003836
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003837 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303838 out->send_next_track_params = false;
3839 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003840 out->offload_state = OFFLOAD_STATE_IDLE;
3841 out->playback_started = 0;
3842
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003843 audio_extn_dts_create_state_notifier_node(out->usecase);
3844
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003845 create_offload_callback_thread(out);
3846 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3847 __func__, config->offload_info.version,
3848 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303849
3850 /* Disable gapless if any of the following is true
3851 * passthrough playback
3852 * AV playback
3853 * Direct PCM playback
3854 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303855 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303856 config->offload_info.has_video ||
3857 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3858 check_and_set_gapless_mode(adev, false);
3859 } else
3860 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003861
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303862 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003863 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3864 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003865 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303866 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003867 if (ret != 0) {
3868 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3869 __func__, ret);
3870 goto error_open;
3871 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003872 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3873 if (config->sample_rate == 0)
3874 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3875 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3876 config->sample_rate != 8000) {
3877 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3878 ret = -EINVAL;
3879 goto error_open;
3880 }
3881 out->sample_rate = config->sample_rate;
3882 out->config.rate = config->sample_rate;
3883 if (config->format == AUDIO_FORMAT_DEFAULT)
3884 config->format = AUDIO_FORMAT_PCM_16_BIT;
3885 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3886 config->format = AUDIO_FORMAT_PCM_16_BIT;
3887 ret = -EINVAL;
3888 goto error_open;
3889 }
3890 out->format = config->format;
3891 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3892 out->config = pcm_config_afe_proxy_playback;
3893 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003894 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303895 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3896 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003897 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3898 out->flags);
3899 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303900 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3901 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3902 out->config = pcm_config_low_latency;
3903 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3904 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3905 out->config = pcm_config_deep_buffer;
3906 } else {
3907 /* primary path is the default path selected if no other outputs are available/suitable */
3908 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3909 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3910 }
3911 out->hal_ip_format = format = out->format;
3912 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3913 out->hal_op_format = pcm_format_to_hal(out->config.format);
3914 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3915 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003916 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303917 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3918 if (out->hal_ip_format != out->hal_op_format) {
3919 uint32_t buffer_size = out->config.period_size *
3920 format_to_bitwidth_table[out->hal_op_format] *
3921 out->config.channels;
3922 out->convert_buffer = calloc(1, buffer_size);
3923 if (out->convert_buffer == NULL){
3924 ALOGE("Allocation failed for convert buffer for size %d",
3925 out->compr_config.fragment_size);
3926 ret = -ENOMEM;
3927 goto error_open;
3928 }
3929 ALOGD("Convert buffer allocated of size %d", buffer_size);
3930 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931 }
3932
Ashish Jain83a6cc22016-06-28 14:34:17 +05303933 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3934 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3935
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003936 /* TODO remove this hardcoding and check why width is zero*/
3937 if (out->bit_width == 0)
3938 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003939 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3940 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003941 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303942 out->bit_width, out->channel_mask,
3943 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003944 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3945 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3946 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003947 if(adev->primary_output == NULL)
3948 adev->primary_output = out;
3949 else {
3950 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003951 ret = -EEXIST;
3952 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003953 }
3954 }
3955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 /* Check if this usecase is already existing */
3957 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003958 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3959 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003962 ret = -EEXIST;
3963 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 }
3965 pthread_mutex_unlock(&adev->lock);
3966
3967 out->stream.common.get_sample_rate = out_get_sample_rate;
3968 out->stream.common.set_sample_rate = out_set_sample_rate;
3969 out->stream.common.get_buffer_size = out_get_buffer_size;
3970 out->stream.common.get_channels = out_get_channels;
3971 out->stream.common.get_format = out_get_format;
3972 out->stream.common.set_format = out_set_format;
3973 out->stream.common.standby = out_standby;
3974 out->stream.common.dump = out_dump;
3975 out->stream.common.set_parameters = out_set_parameters;
3976 out->stream.common.get_parameters = out_get_parameters;
3977 out->stream.common.add_audio_effect = out_add_audio_effect;
3978 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3979 out->stream.get_latency = out_get_latency;
3980 out->stream.set_volume = out_set_volume;
3981 out->stream.write = out_write;
3982 out->stream.get_render_position = out_get_render_position;
3983 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003984 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003986 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003988 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003989 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990
3991 config->format = out->stream.common.get_format(&out->stream.common);
3992 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3993 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3994
3995 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303996 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003997 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003998
3999 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4000 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4001 popcount(out->channel_mask), out->playback_started);
4002
Eric Laurent994a6932013-07-17 11:51:42 -07004003 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004005
4006error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304007 if (out->convert_buffer)
4008 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004009 free(out);
4010 *stream_out = NULL;
4011 ALOGD("%s: exit: ret %d", __func__, ret);
4012 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013}
4014
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004015static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 struct audio_stream_out *stream)
4017{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004018 struct stream_out *out = (struct stream_out *)stream;
4019 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004020 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004021
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304022 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4023
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004024 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304025 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004026 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304027 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004028 if(ret != 0)
4029 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4030 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004031 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004032 out_standby(&stream->common);
4033
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004034 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004035 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004037 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004038 if (out->compr_config.codec != NULL)
4039 free(out->compr_config.codec);
4040 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004041
Ashish Jain83a6cc22016-06-28 14:34:17 +05304042 if (out->convert_buffer != NULL) {
4043 free(out->convert_buffer);
4044 out->convert_buffer = NULL;
4045 }
4046
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004047 if (adev->voice_tx_output == out)
4048 adev->voice_tx_output = NULL;
4049
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004050 pthread_cond_destroy(&out->cond);
4051 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004053 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054}
4055
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004056static void close_compress_sessions(struct audio_device *adev)
4057{
Mingming Yin7b762e72015-03-04 13:47:32 -08004058 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304059 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004060 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004061 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304062
4063 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004064 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304065 if (is_offload_usecase(usecase->id)) {
4066 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004067 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4068 out = usecase->stream.out;
4069 pthread_mutex_unlock(&adev->lock);
4070 out_standby(&out->stream.common);
4071 pthread_mutex_lock(&adev->lock);
4072 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304073 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004074 }
4075 pthread_mutex_unlock(&adev->lock);
4076}
4077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4079{
4080 struct audio_device *adev = (struct audio_device *)dev;
4081 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004083 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004084 int ret;
4085 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004087 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304090 if (!parms)
4091 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004092 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4093 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304094 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304095 if (strstr(snd_card_status, "OFFLINE")) {
4096 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304097 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004098 //close compress sessions on OFFLINE status
4099 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304100 } else if (strstr(snd_card_status, "ONLINE")) {
4101 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304102 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004103 //send dts hpx license if enabled
4104 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304105 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304106 }
4107
4108 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004109 status = voice_set_parameters(adev, parms);
4110 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004111 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004113 status = platform_set_parameters(adev->platform, parms);
4114 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004115 goto done;
4116
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004117 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4118 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004119 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4121 adev->bluetooth_nrec = true;
4122 else
4123 adev->bluetooth_nrec = false;
4124 }
4125
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004126 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4127 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4129 adev->screen_off = false;
4130 else
4131 adev->screen_off = true;
4132 }
4133
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004134 ret = str_parms_get_int(parms, "rotation", &val);
4135 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004136 bool reverse_speakers = false;
4137 switch(val) {
4138 // FIXME: note that the code below assumes that the speakers are in the correct placement
4139 // relative to the user when the device is rotated 90deg from its default rotation. This
4140 // assumption is device-specific, not platform-specific like this code.
4141 case 270:
4142 reverse_speakers = true;
4143 break;
4144 case 0:
4145 case 90:
4146 case 180:
4147 break;
4148 default:
4149 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004150 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004151 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004152 if (status == 0) {
4153 if (adev->speaker_lr_swap != reverse_speakers) {
4154 adev->speaker_lr_swap = reverse_speakers;
4155 // only update the selected device if there is active pcm playback
4156 struct audio_usecase *usecase;
4157 struct listnode *node;
4158 list_for_each(node, &adev->usecase_list) {
4159 usecase = node_to_item(node, struct audio_usecase, list);
4160 if (usecase->type == PCM_PLAYBACK) {
4161 select_devices(adev, usecase->id);
4162 break;
4163 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004164 }
4165 }
4166 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004167 }
4168
Mingming Yin514a8bc2014-07-29 15:22:21 -07004169 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4170 if (ret >= 0) {
4171 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4172 adev->bt_wb_speech_enabled = true;
4173 else
4174 adev->bt_wb_speech_enabled = false;
4175 }
4176
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004177 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4178 if (ret >= 0) {
4179 val = atoi(value);
4180 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4181 ALOGV("cache new edid");
4182 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004183 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4184 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004185 /*
4186 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4187 * Per AudioPolicyManager, USB device is higher priority than WFD.
4188 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4189 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4190 * starting voice call on USB
4191 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004192 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4193 if (ret >= 0) {
4194 audio_extn_usb_add_device(val, atoi(value));
4195 }
vivek mehta344576a2016-04-12 18:56:03 -07004196 ALOGV("detected USB connect .. disable proxy");
4197 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004198 }
4199 }
4200
4201 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4202 if (ret >= 0) {
4203 val = atoi(value);
4204 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4205 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004206 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004207 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4208 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4209 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4210 if (ret >= 0) {
4211 audio_extn_usb_remove_device(val, atoi(value));
4212 }
vivek mehta344576a2016-04-12 18:56:03 -07004213 ALOGV("detected USB disconnect .. enable proxy");
4214 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004215 }
4216 }
4217
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004218 audio_extn_set_parameters(adev, parms);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304219 // reconfigure should be done only after updating a2dpstate in audio extn
4220 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4221 if (ret >= 0) {
4222 struct audio_usecase *usecase;
4223 struct listnode *node;
4224 list_for_each(node, &adev->usecase_list) {
4225 usecase = node_to_item(node, struct audio_usecase, list);
4226 if ((usecase->type == PCM_PLAYBACK) &&
4227 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4228 ALOGD("reconfigure a2dp... forcing device switch");
4229 //force device switch to re configure encoder
4230 select_devices(adev, usecase->id);
4231 break;
4232 }
4233 }
4234 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004235
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004236done:
4237 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004238 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304239error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004240 ALOGV("%s: exit with code(%d)", __func__, status);
4241 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004242}
4243
4244static char* adev_get_parameters(const struct audio_hw_device *dev,
4245 const char *keys)
4246{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004247 struct audio_device *adev = (struct audio_device *)dev;
4248 struct str_parms *reply = str_parms_create();
4249 struct str_parms *query = str_parms_create_str(keys);
4250 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304251 char value[256] = {0};
4252 int ret = 0;
4253
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004254 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004255 if (reply) {
4256 str_parms_destroy(reply);
4257 }
4258 if (query) {
4259 str_parms_destroy(query);
4260 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004261 ALOGE("adev_get_parameters: failed to create query or reply");
4262 return NULL;
4263 }
4264
Naresh Tannirud7205b62014-06-20 02:54:48 +05304265 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4266 sizeof(value));
4267 if (ret >=0) {
4268 int val = 1;
4269 pthread_mutex_lock(&adev->snd_card_status.lock);
4270 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4271 val = 0;
4272 pthread_mutex_unlock(&adev->snd_card_status.lock);
4273 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4274 goto exit;
4275 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004276
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004277 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004278 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004279 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004280 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304281 pthread_mutex_unlock(&adev->lock);
4282
Naresh Tannirud7205b62014-06-20 02:54:48 +05304283exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004284 str = str_parms_to_str(reply);
4285 str_parms_destroy(query);
4286 str_parms_destroy(reply);
4287
4288 ALOGV("%s: exit: returns - %s", __func__, str);
4289 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290}
4291
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004292static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293{
4294 return 0;
4295}
4296
4297static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4298{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004299 int ret;
4300 struct audio_device *adev = (struct audio_device *)dev;
4301 pthread_mutex_lock(&adev->lock);
4302 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004303 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004304 pthread_mutex_unlock(&adev->lock);
4305 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306}
4307
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004308static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4309 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310{
4311 return -ENOSYS;
4312}
4313
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004314static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4315 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316{
4317 return -ENOSYS;
4318}
4319
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004320static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4321 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322{
4323 return -ENOSYS;
4324}
4325
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004326static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4327 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328{
4329 return -ENOSYS;
4330}
4331
4332static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4333{
4334 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 pthread_mutex_lock(&adev->lock);
4337 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004338 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004340 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004341 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004342 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004343 adev->current_call_output = NULL;
4344 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345 }
4346 pthread_mutex_unlock(&adev->lock);
4347 return 0;
4348}
4349
4350static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4351{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004352 int ret;
4353
4354 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004355 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004356 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4357 pthread_mutex_unlock(&adev->lock);
4358
4359 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360}
4361
4362static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4363{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004364 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004365 return 0;
4366}
4367
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004368static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004369 const struct audio_config *config)
4370{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004371 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004373 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4374 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375}
4376
4377static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004378 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 audio_devices_t devices,
4380 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004381 struct audio_stream_in **stream_in,
4382 audio_input_flags_t flags __unused,
4383 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004384 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385{
4386 struct audio_device *adev = (struct audio_device *)dev;
4387 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004388 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004389 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004390 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304393 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4394 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304396 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004397
4398 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004399
4400 if (!in) {
4401 ALOGE("failed to allocate input stream");
4402 return -ENOMEM;
4403 }
4404
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304405 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304406 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4407 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004408 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004409 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411 in->stream.common.get_sample_rate = in_get_sample_rate;
4412 in->stream.common.set_sample_rate = in_set_sample_rate;
4413 in->stream.common.get_buffer_size = in_get_buffer_size;
4414 in->stream.common.get_channels = in_get_channels;
4415 in->stream.common.get_format = in_get_format;
4416 in->stream.common.set_format = in_set_format;
4417 in->stream.common.standby = in_standby;
4418 in->stream.common.dump = in_dump;
4419 in->stream.common.set_parameters = in_set_parameters;
4420 in->stream.common.get_parameters = in_get_parameters;
4421 in->stream.common.add_audio_effect = in_add_audio_effect;
4422 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4423 in->stream.set_gain = in_set_gain;
4424 in->stream.read = in_read;
4425 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4426
4427 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004428 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430 in->standby = 1;
4431 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004432 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004433 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434
4435 /* Update config params with the requested sample rate and channels */
4436 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004437 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4438 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4439 is_low_latency = true;
4440#if LOW_LATENCY_CAPTURE_USE_CASE
4441 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4442#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004443 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004444 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004445
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004446 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004447 if (in->realtime) {
4448 in->config = pcm_config_audio_capture_rt;
4449 in->sample_rate = in->config.rate;
4450 in->af_period_multiplier = af_period_multiplier;
4451 } else {
4452 in->config = pcm_config_audio_capture;
4453 in->config.rate = config->sample_rate;
4454 in->sample_rate = config->sample_rate;
4455 in->af_period_multiplier = 1;
4456 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304457 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004459 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304460 if (adev->mode != AUDIO_MODE_IN_CALL) {
4461 ret = -EINVAL;
4462 goto err_open;
4463 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004464 if (config->sample_rate == 0)
4465 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4466 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4467 config->sample_rate != 8000) {
4468 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4469 ret = -EINVAL;
4470 goto err_open;
4471 }
4472 if (config->format == AUDIO_FORMAT_DEFAULT)
4473 config->format = AUDIO_FORMAT_PCM_16_BIT;
4474 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4475 config->format = AUDIO_FORMAT_PCM_16_BIT;
4476 ret = -EINVAL;
4477 goto err_open;
4478 }
4479
4480 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4481 in->config = pcm_config_afe_proxy_record;
4482 in->config.channels = channel_count;
4483 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304484 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304485 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4486 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004487 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004488 audio_extn_compr_cap_format_supported(config->format) &&
4489 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004490 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004491 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304492 /* restrict 24 bit capture for unprocessed source only
4493 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4494 */
4495 if (config->format == AUDIO_FORMAT_DEFAULT) {
4496 config->format = AUDIO_FORMAT_PCM_16_BIT;
4497 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4498 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4499 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4500 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4501 bool ret_error = false;
4502 in->bit_width = 24;
4503 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4504 from HAL is 24_packed and 8_24
4505 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4506 24_packed return error indicating supported format is 24_packed
4507 *> In case of any other source requesting 24 bit or float return error
4508 indicating format supported is 16 bit only.
4509
4510 on error flinger will retry with supported format passed
4511 */
4512 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4513 (source != AUDIO_SOURCE_CAMCORDER)) {
4514 config->format = AUDIO_FORMAT_PCM_16_BIT;
4515 if( config->sample_rate > 48000)
4516 config->sample_rate = 48000;
4517 ret_error = true;
4518 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4519 in->config.format = PCM_FORMAT_S24_3LE;
4520 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4521 in->config.format = PCM_FORMAT_S24_LE;
4522 } else {
4523 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4524 ret_error = true;
4525 }
4526
4527 if (ret_error) {
4528 ret = -EINVAL;
4529 goto err_open;
4530 }
4531 }
4532
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004533 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004534 if (!in->realtime) {
4535 in->format = config->format;
4536 frame_size = audio_stream_in_frame_size(&in->stream);
4537 buffer_size = get_input_buffer_size(config->sample_rate,
4538 config->format,
4539 channel_count,
4540 is_low_latency);
4541 in->config.period_size = buffer_size / frame_size;
4542 }
4543
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004544 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4545 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4546 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004547 (in->config.rate == 8000 || in->config.rate == 16000 ||
4548 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004549 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4550 voice_extn_compress_voip_open_input_stream(in);
4551 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004552 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004554 /* This stream could be for sound trigger lab,
4555 get sound trigger pcm if present */
4556 audio_extn_sound_trigger_check_and_get_session(in);
4557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004559 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004560 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561
4562err_open:
4563 free(in);
4564 *stream_in = NULL;
4565 return ret;
4566}
4567
4568static void adev_close_input_stream(struct audio_hw_device *dev,
4569 struct audio_stream_in *stream)
4570{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004571 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004572 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004573 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304574
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304575 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004576
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304577 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004578 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304579
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004580 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304581 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004582 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304583 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004584 if (ret != 0)
4585 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4586 __func__, ret);
4587 } else
4588 in_standby(&stream->common);
4589
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004590 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004591 audio_extn_ssr_deinit();
4592 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593
Mingming Yine62d7842013-10-25 16:26:03 -07004594 if(audio_extn_compr_cap_enabled() &&
4595 audio_extn_compr_cap_format_supported(in->config.format))
4596 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004597
Mingming Yinfd7607b2016-01-22 12:48:44 -08004598 if (in->is_st_session) {
4599 ALOGV("%s: sound trigger pcm stop lab", __func__);
4600 audio_extn_sound_trigger_stop_lab(in);
4601 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004602 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004603 return;
4604}
4605
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004606static int adev_dump(const audio_hw_device_t *device __unused,
4607 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608{
4609 return 0;
4610}
4611
4612static int adev_close(hw_device_t *device)
4613{
4614 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004615
4616 if (!adev)
4617 return 0;
4618
4619 pthread_mutex_lock(&adev_init_lock);
4620
4621 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004622 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004623 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004624 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004625 audio_route_free(adev->audio_route);
4626 free(adev->snd_dev_ref_cnt);
4627 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004628 if (adev->adm_deinit)
4629 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004630 free(device);
4631 adev = NULL;
4632 }
4633 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 return 0;
4636}
4637
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004638/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4639 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4640 * just that it _might_ work.
4641 */
4642static int period_size_is_plausible_for_low_latency(int period_size)
4643{
4644 switch (period_size) {
4645 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004646 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004647 case 240:
4648 case 320:
4649 case 480:
4650 return 1;
4651 default:
4652 return 0;
4653 }
4654}
4655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656static int adev_open(const hw_module_t *module, const char *name,
4657 hw_device_t **device)
4658{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004659 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4661
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004662 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004663 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004664 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004665 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004666 ALOGD("%s: returning existing instance of adev", __func__);
4667 ALOGD("%s: exit", __func__);
4668 pthread_mutex_unlock(&adev_init_lock);
4669 return 0;
4670 }
4671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004672 adev = calloc(1, sizeof(struct audio_device));
4673
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004674 if (!adev) {
4675 pthread_mutex_unlock(&adev_init_lock);
4676 return -ENOMEM;
4677 }
4678
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004679 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4682 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4683 adev->device.common.module = (struct hw_module_t *)module;
4684 adev->device.common.close = adev_close;
4685
4686 adev->device.init_check = adev_init_check;
4687 adev->device.set_voice_volume = adev_set_voice_volume;
4688 adev->device.set_master_volume = adev_set_master_volume;
4689 adev->device.get_master_volume = adev_get_master_volume;
4690 adev->device.set_master_mute = adev_set_master_mute;
4691 adev->device.get_master_mute = adev_get_master_mute;
4692 adev->device.set_mode = adev_set_mode;
4693 adev->device.set_mic_mute = adev_set_mic_mute;
4694 adev->device.get_mic_mute = adev_get_mic_mute;
4695 adev->device.set_parameters = adev_set_parameters;
4696 adev->device.get_parameters = adev_get_parameters;
4697 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4698 adev->device.open_output_stream = adev_open_output_stream;
4699 adev->device.close_output_stream = adev_close_output_stream;
4700 adev->device.open_input_stream = adev_open_input_stream;
4701 adev->device.close_input_stream = adev_close_input_stream;
4702 adev->device.dump = adev_dump;
4703
4704 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004706 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004707 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004710 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004711 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004712 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004713 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004714 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004715 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004716 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004717 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304718 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304719 adev->perf_lock_opts[0] = 0x101;
4720 adev->perf_lock_opts[1] = 0x20E;
4721 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304722
4723 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4724 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004726 adev->platform = platform_init(adev);
4727 if (!adev->platform) {
4728 free(adev->snd_dev_ref_cnt);
4729 free(adev);
4730 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4731 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004732 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004733 return -EINVAL;
4734 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004735
Naresh Tanniru4c630392014-05-12 01:05:52 +05304736 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4737
Eric Laurentc4aef752013-09-12 17:45:53 -07004738 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4739 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4740 if (adev->visualizer_lib == NULL) {
4741 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4742 } else {
4743 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4744 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004745 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004746 "visualizer_hal_start_output");
4747 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004748 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004749 "visualizer_hal_stop_output");
4750 }
4751 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004752 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004753 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004754
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004755 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4756 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4757 if (adev->offload_effects_lib == NULL) {
4758 ALOGE("%s: DLOPEN failed for %s", __func__,
4759 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4760 } else {
4761 ALOGV("%s: DLOPEN successful for %s", __func__,
4762 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4763 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304764 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004765 "offload_effects_bundle_hal_start_output");
4766 adev->offload_effects_stop_output =
4767 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4768 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004769 adev->offload_effects_set_hpx_state =
4770 (int (*)(bool))dlsym(adev->offload_effects_lib,
4771 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304772 adev->offload_effects_get_parameters =
4773 (void (*)(struct str_parms *, struct str_parms *))
4774 dlsym(adev->offload_effects_lib,
4775 "offload_effects_bundle_get_parameters");
4776 adev->offload_effects_set_parameters =
4777 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4778 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004779 }
4780 }
4781
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004782 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4783 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4784 if (adev->adm_lib == NULL) {
4785 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4786 } else {
4787 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4788 adev->adm_init = (adm_init_t)
4789 dlsym(adev->adm_lib, "adm_init");
4790 adev->adm_deinit = (adm_deinit_t)
4791 dlsym(adev->adm_lib, "adm_deinit");
4792 adev->adm_register_input_stream = (adm_register_input_stream_t)
4793 dlsym(adev->adm_lib, "adm_register_input_stream");
4794 adev->adm_register_output_stream = (adm_register_output_stream_t)
4795 dlsym(adev->adm_lib, "adm_register_output_stream");
4796 adev->adm_deregister_stream = (adm_deregister_stream_t)
4797 dlsym(adev->adm_lib, "adm_deregister_stream");
4798 adev->adm_request_focus = (adm_request_focus_t)
4799 dlsym(adev->adm_lib, "adm_request_focus");
4800 adev->adm_abandon_focus = (adm_abandon_focus_t)
4801 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004802 adev->adm_set_config = (adm_set_config_t)
4803 dlsym(adev->adm_lib, "adm_set_config");
4804 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4805 dlsym(adev->adm_lib, "adm_request_focus_v2");
4806 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4807 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4808 adev->adm_on_routing_change = (adm_on_routing_change_t)
4809 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004810 }
4811 }
4812
Mingming Yin514a8bc2014-07-29 15:22:21 -07004813 adev->bt_wb_speech_enabled = false;
4814
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004815 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816 *device = &adev->device.common;
4817
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004818 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4819 &adev->streams_output_cfg_list);
4820
Kiran Kandi910e1862013-10-29 13:29:42 -07004821 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004822
4823 char value[PROPERTY_VALUE_MAX];
4824 int trial;
4825 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4826 trial = atoi(value);
4827 if (period_size_is_plausible_for_low_latency(trial)) {
4828 pcm_config_low_latency.period_size = trial;
4829 pcm_config_low_latency.start_threshold = trial / 4;
4830 pcm_config_low_latency.avail_min = trial / 4;
4831 configured_low_latency_capture_period_size = trial;
4832 }
4833 }
4834 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4835 trial = atoi(value);
4836 if (period_size_is_plausible_for_low_latency(trial)) {
4837 configured_low_latency_capture_period_size = trial;
4838 }
4839 }
4840
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004841 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4842 af_period_multiplier = atoi(value);
4843 if (af_period_multiplier < 0)
4844 af_period_multiplier = 2;
4845 else if (af_period_multiplier > 4)
4846 af_period_multiplier = 4;
4847
4848 ALOGV("new period_multiplier = %d", af_period_multiplier);
4849 }
4850
vivek mehta446c3962015-09-14 10:57:35 -07004851 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004852 pthread_mutex_unlock(&adev_init_lock);
4853
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004854 if (adev->adm_init)
4855 adev->adm_data = adev->adm_init();
4856
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304857 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004858 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859 return 0;
4860}
4861
4862static struct hw_module_methods_t hal_module_methods = {
4863 .open = adev_open,
4864};
4865
4866struct audio_module HAL_MODULE_INFO_SYM = {
4867 .common = {
4868 .tag = HARDWARE_MODULE_TAG,
4869 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4870 .hal_api_version = HARDWARE_HAL_API_VERSION,
4871 .id = AUDIO_HARDWARE_MODULE_ID,
4872 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004873 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874 .methods = &hal_module_methods,
4875 },
4876};