blob: db1e399d82dcbd56185593a701283e16baf35b5f [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)) ||
1239 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001240 in_snd_device = vc_usecase->in_snd_device;
1241 out_snd_device = vc_usecase->out_snd_device;
1242 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001243 } else if (voice_extn_compress_voip_is_active(adev)) {
1244 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001245 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001246 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1247 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001248 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001249 in_snd_device = voip_usecase->in_snd_device;
1250 out_snd_device = voip_usecase->out_snd_device;
1251 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001252 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001253 hfp_ucid = audio_extn_hfp_get_usecase();
1254 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001255 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001256 in_snd_device = hfp_usecase->in_snd_device;
1257 out_snd_device = hfp_usecase->out_snd_device;
1258 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259 }
1260 if (usecase->type == PCM_PLAYBACK) {
1261 usecase->devices = usecase->stream.out->devices;
1262 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001263 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001264 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001265 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001266 if (usecase->stream.out == adev->primary_output &&
1267 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001268 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001269 select_devices(adev, adev->active_input->usecase);
1270 }
1271 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 } else if (usecase->type == PCM_CAPTURE) {
1273 usecase->devices = usecase->stream.in->device;
1274 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001275 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001276 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001277 if (adev->active_input &&
1278 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301279 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1280 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1281 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001282 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001283 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001284 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1285 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001286 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001287 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001288 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 }
1290 }
1291
1292 if (out_snd_device == usecase->out_snd_device &&
1293 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301294
1295 if (!force_device_switch(usecase))
1296 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 }
1298
sangwoobc677242013-08-08 16:53:43 +09001299 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001300 out_snd_device, platform_get_snd_device_name(out_snd_device),
1301 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001303 /*
1304 * Limitation: While in call, to do a device switch we need to disable
1305 * and enable both RX and TX devices though one of them is same as current
1306 * device.
1307 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001308 if ((usecase->type == VOICE_CALL) &&
1309 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1310 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001311 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001312 }
1313
1314 if (((usecase->type == VOICE_CALL) ||
1315 (usecase->type == VOIP_CALL)) &&
1316 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1317 /* Disable sidetone only if voice/voip call already exists */
1318 if (voice_is_call_state_active(adev) ||
1319 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001320 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001321 }
1322
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323 /* Disable current sound devices */
1324 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001325 disable_audio_route(adev, usecase);
1326 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001327 }
1328
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001330 disable_audio_route(adev, usecase);
1331 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332 }
1333
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001334 /* Applicable only on the targets that has external modem.
1335 * New device information should be sent to modem before enabling
1336 * the devices to reduce in-call device switch time.
1337 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001338 if ((usecase->type == VOICE_CALL) &&
1339 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1340 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001341 status = platform_switch_voice_call_enable_device_config(adev->platform,
1342 out_snd_device,
1343 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001344 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001345
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001346 /* Enable new sound devices */
1347 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001348 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001349 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 }
1351
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001352 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301353 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001354 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001355 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001356
Avinash Vaish71a8b972014-07-24 15:36:33 +05301357 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001358 status = platform_switch_voice_call_device_post(adev->platform,
1359 out_snd_device,
1360 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301361 enable_audio_route_for_voice_usecases(adev, usecase);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001362 /* Enable sidetone only if voice/voip call already exists */
1363 if (voice_is_call_state_active(adev) ||
1364 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001365 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301366 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001367
sangwoo170731f2013-06-08 15:36:36 +09001368 usecase->in_snd_device = in_snd_device;
1369 usecase->out_snd_device = out_snd_device;
1370
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301371 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001372 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301373 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001374 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301375 usecase->stream.out->flags,
1376 usecase->stream.out->format,
1377 usecase->stream.out->sample_rate,
1378 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301379 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301380 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001381 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301382 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001383
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001384 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001385
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001386 /* Applicable only on the targets that has external modem.
1387 * Enable device command should be sent to modem only after
1388 * enabling voice call mixer controls
1389 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001390 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001391 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1392 out_snd_device,
1393 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301394 ALOGD("%s: done",__func__);
1395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396 return status;
1397}
1398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399static int stop_input_stream(struct stream_in *in)
1400{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301401 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 struct audio_usecase *uc_info;
1403 struct audio_device *adev = in->dev;
1404
Eric Laurentc8400632013-02-14 19:04:54 -08001405 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406
Eric Laurent994a6932013-07-17 11:51:42 -07001407 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409 uc_info = get_usecase_from_list(adev, in->usecase);
1410 if (uc_info == NULL) {
1411 ALOGE("%s: Could not find the usecase (%d) in the list",
1412 __func__, in->usecase);
1413 return -EINVAL;
1414 }
1415
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001416 /* Close in-call recording streams */
1417 voice_check_and_stop_incall_rec_usecase(adev, in);
1418
Eric Laurent150dbfe2013-02-27 14:31:02 -08001419 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001420 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421
1422 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001423 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001425 list_remove(&uc_info->list);
1426 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427
Eric Laurent994a6932013-07-17 11:51:42 -07001428 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 return ret;
1430}
1431
1432int start_input_stream(struct stream_in *in)
1433{
1434 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001435 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436 struct audio_usecase *uc_info;
1437 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301438 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439
Mingming Yin2664a5b2015-09-03 10:53:11 -07001440 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1441 if (get_usecase_from_list(adev, usecase) == NULL)
1442 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301443 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1444 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001445
Naresh Tanniru80659832014-06-04 18:17:56 +05301446
1447 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301448 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301449 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301450 goto error_config;
1451 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301452
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001453 /* Check if source matches incall recording usecase criteria */
1454 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1455 if (ret)
1456 goto error_config;
1457 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001458 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1459
1460 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1461 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1462 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001463 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001464 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001465
Eric Laurentb23d5282013-05-14 15:27:20 -07001466 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467 if (in->pcm_device_id < 0) {
1468 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1469 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001470 ret = -EINVAL;
1471 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001472 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001473
1474 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001476
1477 if (!uc_info) {
1478 ret = -ENOMEM;
1479 goto error_config;
1480 }
1481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482 uc_info->id = in->usecase;
1483 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001484 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001485 uc_info->devices = in->device;
1486 uc_info->in_snd_device = SND_DEVICE_NONE;
1487 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001489 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301490 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1491 adev->perf_lock_opts,
1492 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301495 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1496 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001497
1498 unsigned int flags = PCM_IN;
1499 unsigned int pcm_open_retry_count = 0;
1500
1501 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1502 flags |= PCM_MMAP | PCM_NOIRQ;
1503 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001504 } else if (in->realtime) {
1505 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001506 }
1507
1508 while (1) {
1509 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1510 flags, &in->config);
1511 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1512 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1513 if (in->pcm != NULL) {
1514 pcm_close(in->pcm);
1515 in->pcm = NULL;
1516 }
1517 if (pcm_open_retry_count-- == 0) {
1518 ret = -EIO;
1519 goto error_open;
1520 }
1521 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1522 continue;
1523 }
1524 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001526
1527 ALOGV("%s: pcm_prepare", __func__);
1528 ret = pcm_prepare(in->pcm);
1529 if (ret < 0) {
1530 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1531 pcm_close(in->pcm);
1532 in->pcm = NULL;
1533 goto error_open;
1534 }
1535
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001536 register_in_stream(in);
1537 if (in->realtime) {
1538 ret = pcm_start(in->pcm);
1539 if (ret < 0)
1540 goto error_open;
1541 }
1542
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301543 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001544 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001545
Eric Laurentc8400632013-02-14 19:04:54 -08001546 return ret;
1547
1548error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301549 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001551error_config:
1552 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301553 /*
1554 * sleep 50ms to allow sufficient time for kernel
1555 * drivers to recover incases like SSR.
1556 */
1557 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001558 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001559
1560 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001561}
1562
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001563void lock_input_stream(struct stream_in *in)
1564{
1565 pthread_mutex_lock(&in->pre_lock);
1566 pthread_mutex_lock(&in->lock);
1567 pthread_mutex_unlock(&in->pre_lock);
1568}
1569
1570void lock_output_stream(struct stream_out *out)
1571{
1572 pthread_mutex_lock(&out->pre_lock);
1573 pthread_mutex_lock(&out->lock);
1574 pthread_mutex_unlock(&out->pre_lock);
1575}
1576
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577/* must be called with out->lock locked */
1578static int send_offload_cmd_l(struct stream_out* out, int command)
1579{
1580 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1581
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001582 if (!cmd) {
1583 ALOGE("failed to allocate mem for command 0x%x", command);
1584 return -ENOMEM;
1585 }
1586
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001587 ALOGVV("%s %d", __func__, command);
1588
1589 cmd->cmd = command;
1590 list_add_tail(&out->offload_cmd_list, &cmd->node);
1591 pthread_cond_signal(&out->offload_cond);
1592 return 0;
1593}
1594
1595/* must be called iwth out->lock locked */
1596static void stop_compressed_output_l(struct stream_out *out)
1597{
1598 out->offload_state = OFFLOAD_STATE_IDLE;
1599 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001600 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001601 if (out->compr != NULL) {
1602 compress_stop(out->compr);
1603 while (out->offload_thread_blocked) {
1604 pthread_cond_wait(&out->cond, &out->lock);
1605 }
1606 }
1607}
1608
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001609bool is_offload_usecase(audio_usecase_t uc_id)
1610{
1611 unsigned int i;
1612 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1613 if (uc_id == offload_usecases[i])
1614 return true;
1615 }
1616 return false;
1617}
1618
vivek mehta446c3962015-09-14 10:57:35 -07001619static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001620{
vivek mehta446c3962015-09-14 10:57:35 -07001621 audio_usecase_t ret_uc = USECASE_INVALID;
1622 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001623 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001624 if (!adev->multi_offload_enable) {
1625 if (is_direct_pcm)
1626 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1627 else
1628 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001629
vivek mehta446c3962015-09-14 10:57:35 -07001630 pthread_mutex_lock(&adev->lock);
1631 if (get_usecase_from_list(adev, ret_uc) != NULL)
1632 ret_uc = USECASE_INVALID;
1633 pthread_mutex_unlock(&adev->lock);
1634
1635 return ret_uc;
1636 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001637
1638 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001639 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1640 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1641 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1642 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001643 break;
1644 }
1645 }
vivek mehta446c3962015-09-14 10:57:35 -07001646
1647 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1648 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001649}
1650
1651static void free_offload_usecase(struct audio_device *adev,
1652 audio_usecase_t uc_id)
1653{
vivek mehta446c3962015-09-14 10:57:35 -07001654 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001655 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001656
1657 if (!adev->multi_offload_enable)
1658 return;
1659
1660 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1661 if (offload_usecases[offload_uc_index] == uc_id) {
1662 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001663 break;
1664 }
1665 }
1666 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1667}
1668
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001669static void *offload_thread_loop(void *context)
1670{
1671 struct stream_out *out = (struct stream_out *) context;
1672 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001673 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001674
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001675 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1676 set_sched_policy(0, SP_FOREGROUND);
1677 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1678
1679 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001680 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 for (;;) {
1682 struct offload_cmd *cmd = NULL;
1683 stream_callback_event_t event;
1684 bool send_callback = false;
1685
1686 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1687 __func__, list_empty(&out->offload_cmd_list),
1688 out->offload_state);
1689 if (list_empty(&out->offload_cmd_list)) {
1690 ALOGV("%s SLEEPING", __func__);
1691 pthread_cond_wait(&out->offload_cond, &out->lock);
1692 ALOGV("%s RUNNING", __func__);
1693 continue;
1694 }
1695
1696 item = list_head(&out->offload_cmd_list);
1697 cmd = node_to_item(item, struct offload_cmd, node);
1698 list_remove(item);
1699
1700 ALOGVV("%s STATE %d CMD %d out->compr %p",
1701 __func__, out->offload_state, cmd->cmd, out->compr);
1702
1703 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1704 free(cmd);
1705 break;
1706 }
1707
1708 if (out->compr == NULL) {
1709 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001710 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001711 pthread_cond_signal(&out->cond);
1712 continue;
1713 }
1714 out->offload_thread_blocked = true;
1715 pthread_mutex_unlock(&out->lock);
1716 send_callback = false;
1717 switch(cmd->cmd) {
1718 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001719 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001720 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001721 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001722 send_callback = true;
1723 event = STREAM_CBK_EVENT_WRITE_READY;
1724 break;
1725 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001726 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301727 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001728 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301729 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001730 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301731 if (ret < 0)
1732 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301733 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301734 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001735 compress_drain(out->compr);
1736 else
1737 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301738 if (ret != -ENETRESET) {
1739 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301740 pthread_mutex_lock(&out->lock);
1741 out->send_new_metadata = 1;
1742 out->send_next_track_params = true;
1743 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301744 event = STREAM_CBK_EVENT_DRAIN_READY;
1745 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1746 } else
1747 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748 break;
1749 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001750 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001752 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753 send_callback = true;
1754 event = STREAM_CBK_EVENT_DRAIN_READY;
1755 break;
1756 default:
1757 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1758 break;
1759 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001760 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001761 out->offload_thread_blocked = false;
1762 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001763 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001764 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001766 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 free(cmd);
1768 }
1769
1770 pthread_cond_signal(&out->cond);
1771 while (!list_empty(&out->offload_cmd_list)) {
1772 item = list_head(&out->offload_cmd_list);
1773 list_remove(item);
1774 free(node_to_item(item, struct offload_cmd, node));
1775 }
1776 pthread_mutex_unlock(&out->lock);
1777
1778 return NULL;
1779}
1780
1781static int create_offload_callback_thread(struct stream_out *out)
1782{
1783 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1784 list_init(&out->offload_cmd_list);
1785 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1786 offload_thread_loop, out);
1787 return 0;
1788}
1789
1790static int destroy_offload_callback_thread(struct stream_out *out)
1791{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001792 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 stop_compressed_output_l(out);
1794 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1795
1796 pthread_mutex_unlock(&out->lock);
1797 pthread_join(out->offload_thread, (void **) NULL);
1798 pthread_cond_destroy(&out->offload_cond);
1799
1800 return 0;
1801}
1802
Mingming Yin21854652016-04-13 11:54:02 -07001803static bool allow_hdmi_channel_config(struct audio_device *adev,
1804 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001805{
1806 struct listnode *node;
1807 struct audio_usecase *usecase;
1808 bool ret = true;
1809
Mingming Yin21854652016-04-13 11:54:02 -07001810 if (enable_passthru && !audio_extn_passthru_is_enabled()) {
1811 ret = false;
1812 goto exit;
1813 }
1814
1815 if (audio_extn_passthru_is_active()) {
1816 ALOGI("%s: Compress audio passthrough is active,"
1817 "no HDMI config change allowed", __func__);
1818 ret = false;
1819 goto exit;
1820 }
1821
Eric Laurent07eeafd2013-10-06 12:52:49 -07001822 list_for_each(node, &adev->usecase_list) {
1823 usecase = node_to_item(node, struct audio_usecase, list);
1824 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1825 /*
1826 * If voice call is already existing, do not proceed further to avoid
1827 * disabling/enabling both RX and TX devices, CSD calls, etc.
1828 * Once the voice call done, the HDMI channels can be configured to
1829 * max channels of remaining use cases.
1830 */
1831 if (usecase->id == USECASE_VOICE_CALL) {
Mingming Yin21854652016-04-13 11:54:02 -07001832 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001833 __func__);
1834 ret = false;
1835 break;
1836 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Mingming Yin21854652016-04-13 11:54:02 -07001837 if (!enable_passthru) {
1838 ALOGV("%s: multi channel playback is active, "
1839 "no change in HDMI channels", __func__);
1840 ret = false;
1841 break;
1842 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001843 } else if (is_offload_usecase(usecase->id) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07001844 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin21854652016-04-13 11:54:02 -07001845 if (!enable_passthru) {
1846 ALOGD("%s:multi-channel(%x) compress offload playback is active"
1847 ", no change in HDMI channels", __func__,
1848 usecase->stream.out->channel_mask);
1849 ret = false;
1850 break;
1851 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001852 }
1853 }
1854 }
Mingming Yin21854652016-04-13 11:54:02 -07001855 ALOGV("allow hdmi config %d", ret);
1856exit:
Eric Laurent07eeafd2013-10-06 12:52:49 -07001857 return ret;
1858}
1859
Mingming Yin21854652016-04-13 11:54:02 -07001860static int check_and_set_hdmi_config(struct audio_device *adev,
1861 uint32_t channels,
1862 uint32_t sample_rate,
1863 audio_format_t format,
1864 bool enable_passthru)
Eric Laurent07eeafd2013-10-06 12:52:49 -07001865{
1866 struct listnode *node;
1867 struct audio_usecase *usecase;
Mingming Yin21854652016-04-13 11:54:02 -07001868 int32_t factor = 1;
1869 bool config = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001870
Mingming Yin21854652016-04-13 11:54:02 -07001871 ALOGV("%s channels %d sample_rate %d format:%x enable_passthru:%d",
1872 __func__, channels, sample_rate, format, enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001873
Mingming Yin21854652016-04-13 11:54:02 -07001874 if (channels != adev->cur_hdmi_channels) {
1875 ALOGV("channel does not match current hdmi channels");
1876 config = true;
1877 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001878
Mingming Yin21854652016-04-13 11:54:02 -07001879 if (sample_rate != adev->cur_hdmi_sample_rate) {
1880 ALOGV("sample rate does not match current hdmi sample rate");
1881 config = true;
1882 }
1883
1884 if (format != adev->cur_hdmi_format) {
1885 ALOGV("format does not match current hdmi format");
1886 config = true;
1887 }
1888
1889 /* TBD - add check for bit width */
1890 if (!config) {
1891 ALOGV("No need to config hdmi");
Eric Laurent07eeafd2013-10-06 12:52:49 -07001892 return 0;
1893 }
1894
Mingming Yin21854652016-04-13 11:54:02 -07001895 if (enable_passthru &&
1896 (format == AUDIO_FORMAT_E_AC3)) {
1897 ALOGV("factor 4 for E_AC3 passthru");
1898 factor = 4;
1899 }
1900
1901 platform_set_hdmi_config(adev->platform, channels, factor * sample_rate,
1902 enable_passthru);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001903 adev->cur_hdmi_channels = channels;
Mingming Yin21854652016-04-13 11:54:02 -07001904 adev->cur_hdmi_format = format;
1905 adev->cur_hdmi_sample_rate = sample_rate;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001906
1907 /*
1908 * Deroute all the playback streams routed to HDMI so that
1909 * the back end is deactivated. Note that backend will not
1910 * be deactivated if any one stream is connected to it.
1911 */
1912 list_for_each(node, &adev->usecase_list) {
1913 usecase = node_to_item(node, struct audio_usecase, list);
1914 if (usecase->type == PCM_PLAYBACK &&
1915 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001916 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001917 }
1918 }
1919
Mingming Yin21854652016-04-13 11:54:02 -07001920 bool was_active = audio_extn_keep_alive_is_active();
1921 if (was_active)
1922 audio_extn_keep_alive_stop();
1923
Eric Laurent07eeafd2013-10-06 12:52:49 -07001924 /*
1925 * Enable all the streams disabled above. Now the HDMI backend
1926 * will be activated with new channel configuration
1927 */
1928 list_for_each(node, &adev->usecase_list) {
1929 usecase = node_to_item(node, struct audio_usecase, list);
1930 if (usecase->type == PCM_PLAYBACK &&
1931 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001932 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001933 }
1934 }
1935
Mingming Yin21854652016-04-13 11:54:02 -07001936 if (was_active)
1937 audio_extn_keep_alive_start();
1938
Eric Laurent07eeafd2013-10-06 12:52:49 -07001939 return 0;
1940}
1941
Mingming Yin21854652016-04-13 11:54:02 -07001942/* called with out lock taken */
1943static int check_and_set_hdmi_backend(struct stream_out *out)
1944{
1945 struct audio_device *adev = out->dev;
1946 int ret;
1947 bool enable_passthru = false;
1948
1949 if (!(out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL))
1950 return -1;
1951
1952 ALOGV("%s usecase %s out->format:%x out->bit_width:%d", __func__, use_case_table[out->usecase],out->format,out->bit_width);
1953
1954 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301955 audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07001956 enable_passthru = true;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301957 ALOGV("%s : enable_passthru is set to true", __func__);
Mingming Yin21854652016-04-13 11:54:02 -07001958 }
1959
1960 /* Check if change in HDMI channel config is allowed */
1961 if (!allow_hdmi_channel_config(adev, enable_passthru)) {
1962 return -EPERM;
1963 }
1964
1965 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1966 uint32_t channels;
1967 ALOGV("Offload usecase, enable passthru %d", enable_passthru);
1968
1969 if (enable_passthru) {
1970 audio_extn_passthru_on_start(out);
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301971 audio_extn_passthru_update_stream_configuration(adev, out);
Mingming Yin21854652016-04-13 11:54:02 -07001972 }
1973
1974 /* For pass through case, the backend should be configured as stereo */
1975 channels = enable_passthru ? DEFAULT_HDMI_OUT_CHANNELS :
1976 out->compr_config.codec->ch_in;
1977
1978 ret = check_and_set_hdmi_config(adev, channels,
1979 out->sample_rate, out->format,
1980 enable_passthru);
1981 } else
1982 ret = check_and_set_hdmi_config(adev, out->config.channels,
1983 out->config.rate,
1984 out->format,
1985 false);
1986 return ret;
1987}
1988
1989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990static int stop_output_stream(struct stream_out *out)
1991{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301992 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 struct audio_usecase *uc_info;
1994 struct audio_device *adev = out->dev;
1995
Eric Laurent994a6932013-07-17 11:51:42 -07001996 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001997 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 uc_info = get_usecase_from_list(adev, out->usecase);
1999 if (uc_info == NULL) {
2000 ALOGE("%s: Could not find the usecase (%d) in the list",
2001 __func__, out->usecase);
2002 return -EINVAL;
2003 }
2004
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002005 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302006 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002007 if (adev->visualizer_stop_output != NULL)
2008 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002009
2010 audio_extn_dts_remove_state_notifier_node(out->usecase);
2011
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002012 if (adev->offload_effects_stop_output != NULL)
2013 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2014 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002015
Eric Laurent150dbfe2013-02-27 14:31:02 -08002016 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002017 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002018
2019 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002020 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002022 list_remove(&uc_info->list);
2023 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002025 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302026 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002027 ALOGV("Disable passthrough , reset mixer to pcm");
2028 /* NO_PASSTHROUGH */
2029 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002030
Mingming Yin21854652016-04-13 11:54:02 -07002031 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002032 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2033 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002034
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302035 /* Must be called after removing the usecase from list */
2036 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2037 check_and_set_hdmi_config(adev, DEFAULT_HDMI_OUT_CHANNELS,
2038 DEFAULT_HDMI_OUT_SAMPLE_RATE,
2039 DEFAULT_HDMI_OUT_FORMAT,
2040 false);
Eric Laurent994a6932013-07-17 11:51:42 -07002041 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 return ret;
2043}
2044
2045int start_output_stream(struct stream_out *out)
2046{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 struct audio_usecase *uc_info;
2049 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302050 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002052 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2053 ret = -EINVAL;
2054 goto error_config;
2055 }
2056
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302057 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2058 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2059 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302060
Naresh Tanniru80659832014-06-04 18:17:56 +05302061 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302062 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302063 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302064 goto error_config;
2065 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302066
Eric Laurentb23d5282013-05-14 15:27:20 -07002067 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068 if (out->pcm_device_id < 0) {
2069 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2070 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002071 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002072 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002073 }
2074
2075 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002076
2077 if (!uc_info) {
2078 ret = -ENOMEM;
2079 goto error_config;
2080 }
2081
Mingming Yin21854652016-04-13 11:54:02 -07002082 /* This must be called before adding this usecase to the list */
2083 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2084 /* This call can fail if compress pass thru is already active */
2085 check_and_set_hdmi_backend(out);
2086 }
2087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 uc_info->id = out->usecase;
2089 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002090 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002091 uc_info->devices = out->devices;
2092 uc_info->in_snd_device = SND_DEVICE_NONE;
2093 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002094 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302096 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2097 adev->perf_lock_opts,
2098 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002099 select_devices(adev, out->usecase);
2100
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002101 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2102 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002103 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002104 unsigned int flags = PCM_OUT;
2105 unsigned int pcm_open_retry_count = 0;
2106 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2107 flags |= PCM_MMAP | PCM_NOIRQ;
2108 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002109 } else if (out->realtime) {
2110 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002111 } else
2112 flags |= PCM_MONOTONIC;
2113
2114 while (1) {
2115 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2116 flags, &out->config);
2117 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2118 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2119 if (out->pcm != NULL) {
2120 pcm_close(out->pcm);
2121 out->pcm = NULL;
2122 }
2123 if (pcm_open_retry_count-- == 0) {
2124 ret = -EIO;
2125 goto error_open;
2126 }
2127 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2128 continue;
2129 }
2130 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002132
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002133 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2134 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002135
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002136 ALOGV("%s: pcm_prepare", __func__);
2137 if (pcm_is_ready(out->pcm)) {
2138 ret = pcm_prepare(out->pcm);
2139 if (ret < 0) {
2140 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2141 pcm_close(out->pcm);
2142 out->pcm = NULL;
2143 goto error_open;
2144 }
2145 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002146 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002147 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2148 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002150 out->compr = compress_open(adev->snd_card,
2151 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 COMPRESS_IN, &out->compr_config);
2153 if (out->compr && !is_compress_ready(out->compr)) {
2154 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2155 compress_close(out->compr);
2156 out->compr = NULL;
2157 ret = -EIO;
2158 goto error_open;
2159 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302160 /* compress_open sends params of the track, so reset the flag here */
2161 out->is_compr_metadata_avail = false;
2162
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002163 if (out->offload_callback)
2164 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002165
Fred Oh3f43e742015-03-04 18:42:34 -08002166 /* Since small bufs uses blocking writes, a write will be blocked
2167 for the default max poll time (20s) in the event of an SSR.
2168 Reduce the poll time to observe and deal with SSR faster.
2169 */
Ashish Jain5106d362016-05-11 19:23:33 +05302170 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002171 compress_set_max_poll_wait(out->compr, 1000);
2172 }
2173
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002174 audio_extn_dts_create_state_notifier_node(out->usecase);
2175 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2176 popcount(out->channel_mask),
2177 out->playback_started);
2178
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002179#ifdef DS1_DOLBY_DDP_ENABLED
2180 if (audio_extn_is_dolby_format(out->format))
2181 audio_extn_dolby_send_ddp_endp_params(adev);
2182#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302183 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002184 if (adev->visualizer_start_output != NULL)
2185 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2186 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302187 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002188 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002191
2192 if (ret == 0) {
2193 register_out_stream(out);
2194 if (out->realtime) {
2195 ret = pcm_start(out->pcm);
2196 if (ret < 0)
2197 goto error_open;
2198 }
2199 }
2200
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302201 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002202 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002203
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002204 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302206 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002208error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302209 /*
2210 * sleep 50ms to allow sufficient time for kernel
2211 * drivers to recover incases like SSR.
2212 */
2213 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002214 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215}
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static int check_input_parameters(uint32_t sample_rate,
2218 audio_format_t format,
2219 int channel_count)
2220{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002221 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302223 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2224 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2225 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002226 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302227 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002228
2229 switch (channel_count) {
2230 case 1:
2231 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302232 case 3:
2233 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002234 case 6:
2235 break;
2236 default:
2237 ret = -EINVAL;
2238 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239
2240 switch (sample_rate) {
2241 case 8000:
2242 case 11025:
2243 case 12000:
2244 case 16000:
2245 case 22050:
2246 case 24000:
2247 case 32000:
2248 case 44100:
2249 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302250 case 96000:
2251 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 break;
2253 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002254 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 }
2256
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002257 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258}
2259
2260static size_t get_input_buffer_size(uint32_t sample_rate,
2261 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002262 int channel_count,
2263 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264{
2265 size_t size = 0;
2266
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002267 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2268 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002270 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002271 if (is_low_latency)
2272 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302273
2274 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002276 /* make sure the size is multiple of 32 bytes
2277 * At 48 kHz mono 16-bit PCM:
2278 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2279 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2280 */
2281 size += 0x1f;
2282 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002283
2284 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285}
2286
Ashish Jain5106d362016-05-11 19:23:33 +05302287static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2288{
2289 uint64_t actual_frames_rendered = 0;
2290 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2291
2292 /* This adjustment accounts for buffering after app processor.
2293 * It is based on estimated DSP latency per use case, rather than exact.
2294 */
2295 int64_t platform_latency = platform_render_latency(out->usecase) *
2296 out->sample_rate / 1000000LL;
2297
2298 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2299 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2300 * hence only estimate.
2301 */
2302 int64_t signed_frames = out->written - kernel_buffer_size;
2303
2304 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2305
2306 if (signed_frames > 0)
2307 actual_frames_rendered = signed_frames;
2308
2309 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2310 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2311 (long long int)out->written, (int)kernel_buffer_size,
2312 audio_bytes_per_sample(out->compr_config.codec->format),
2313 popcount(out->channel_mask));
2314
2315 return actual_frames_rendered;
2316}
2317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2319{
2320 struct stream_out *out = (struct stream_out *)stream;
2321
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002322 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323}
2324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002325static int out_set_sample_rate(struct audio_stream *stream __unused,
2326 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327{
2328 return -ENOSYS;
2329}
2330
2331static size_t out_get_buffer_size(const struct audio_stream *stream)
2332{
2333 struct stream_out *out = (struct stream_out *)stream;
2334
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002335 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002337 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2338 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302339 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302340 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002342 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002343 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344}
2345
2346static uint32_t out_get_channels(const struct audio_stream *stream)
2347{
2348 struct stream_out *out = (struct stream_out *)stream;
2349
2350 return out->channel_mask;
2351}
2352
2353static audio_format_t out_get_format(const struct audio_stream *stream)
2354{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 struct stream_out *out = (struct stream_out *)stream;
2356
2357 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358}
2359
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002360static int out_set_format(struct audio_stream *stream __unused,
2361 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362{
2363 return -ENOSYS;
2364}
2365
2366static int out_standby(struct audio_stream *stream)
2367{
2368 struct stream_out *out = (struct stream_out *)stream;
2369 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302371 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2372 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002374 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002376 if (adev->adm_deregister_stream)
2377 adev->adm_deregister_stream(adev->adm_data, out->handle);
2378
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002379 if (is_offload_usecase(out->usecase))
2380 stop_compressed_output_l(out);
2381
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002382 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002384 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2385 voice_extn_compress_voip_close_output_stream(stream);
2386 pthread_mutex_unlock(&adev->lock);
2387 pthread_mutex_unlock(&out->lock);
2388 ALOGD("VOIP output entered standby");
2389 return 0;
2390 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 if (out->pcm) {
2392 pcm_close(out->pcm);
2393 out->pcm = NULL;
2394 }
2395 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002396 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302397 out->send_next_track_params = false;
2398 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002399 out->gapless_mdata.encoder_delay = 0;
2400 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 if (out->compr != NULL) {
2402 compress_close(out->compr);
2403 out->compr = NULL;
2404 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002405 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002407 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408 }
2409 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302410 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 return 0;
2412}
2413
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002414static int out_dump(const struct audio_stream *stream __unused,
2415 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416{
2417 return 0;
2418}
2419
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002420static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2421{
2422 int ret = 0;
2423 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002424
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002425 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002426 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002427 return -EINVAL;
2428 }
2429
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302430 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002431
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002432 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2433 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302434 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002435 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002436 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2437 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302438 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002439 }
2440
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002441 ALOGV("%s new encoder delay %u and padding %u", __func__,
2442 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2443
2444 return 0;
2445}
2446
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002447static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2448{
2449 return out == adev->primary_output || out == adev->voice_tx_output;
2450}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2453{
2454 struct stream_out *out = (struct stream_out *)stream;
2455 struct audio_device *adev = out->dev;
2456 struct str_parms *parms;
2457 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002458 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459
sangwoobc677242013-08-08 16:53:43 +09002460 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002461 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302463 if (!parms)
2464 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002465 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2466 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002468 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002469 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002471 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002472 * When HDMI cable is unplugged the music playback is paused and
2473 * the policy manager sends routing=0. But the audioflinger continues
2474 * to write data until standby time (3sec). As the HDMI core is
2475 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002476 * Avoid this by routing audio to speaker until standby.
2477 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002478 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2479 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302480 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002481 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2482 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002483 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302484 /*
2485 * When A2DP is disconnected the
2486 * music playback is paused and the policy manager sends routing=0
2487 * But the audioflingercontinues to write data until standby time
2488 * (3sec). As BT is turned off, the write gets blocked.
2489 * Avoid this by routing audio to speaker until standby.
2490 */
2491 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2492 (val == AUDIO_DEVICE_NONE)) {
2493 val = AUDIO_DEVICE_OUT_SPEAKER;
2494 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002495
2496 /*
2497 * select_devices() call below switches all the usecases on the same
2498 * backend to the new device. Refer to check_usecases_codec_backend() in
2499 * the select_devices(). But how do we undo this?
2500 *
2501 * For example, music playback is active on headset (deep-buffer usecase)
2502 * and if we go to ringtones and select a ringtone, low-latency usecase
2503 * will be started on headset+speaker. As we can't enable headset+speaker
2504 * and headset devices at the same time, select_devices() switches the music
2505 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2506 * So when the ringtone playback is completed, how do we undo the same?
2507 *
2508 * We are relying on the out_set_parameters() call on deep-buffer output,
2509 * once the ringtone playback is ended.
2510 * NOTE: We should not check if the current devices are same as new devices.
2511 * Because select_devices() must be called to switch back the music
2512 * playback to headset.
2513 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002514 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002515 audio_devices_t new_dev = val;
2516 bool same_dev = out->devices == new_dev;
2517 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002518
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002519 if (output_drives_call(adev, out)) {
2520 if(!voice_is_in_call(adev)) {
2521 if (adev->mode == AUDIO_MODE_IN_CALL) {
2522 adev->current_call_output = out;
2523 ret = voice_start_call(adev);
2524 }
2525 } else {
2526 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002527 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002528 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002529 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002530
2531 if (!out->standby) {
2532 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2533 adev->perf_lock_opts,
2534 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002535 if (!same_dev) {
2536 ALOGV("update routing change");
2537 out->routing_change = true;
2538 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002539 select_devices(adev, out->usecase);
2540 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2541 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002542 }
2543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002545 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002547
2548 if (out == adev->primary_output) {
2549 pthread_mutex_lock(&adev->lock);
2550 audio_extn_set_parameters(adev, parms);
2551 pthread_mutex_unlock(&adev->lock);
2552 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002553 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002554 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002555 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002556
2557 audio_extn_dts_create_state_notifier_node(out->usecase);
2558 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2559 popcount(out->channel_mask),
2560 out->playback_started);
2561
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002562 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002563 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302566error:
Eric Laurent994a6932013-07-17 11:51:42 -07002567 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 return ret;
2569}
2570
2571static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2572{
2573 struct stream_out *out = (struct stream_out *)stream;
2574 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002575 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 char value[256];
2577 struct str_parms *reply = str_parms_create();
2578 size_t i, j;
2579 int ret;
2580 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002581
2582 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002583 if (reply) {
2584 str_parms_destroy(reply);
2585 }
2586 if (query) {
2587 str_parms_destroy(query);
2588 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002589 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2590 return NULL;
2591 }
2592
Eric Laurent994a6932013-07-17 11:51:42 -07002593 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2595 if (ret >= 0) {
2596 value[0] = '\0';
2597 i = 0;
2598 while (out->supported_channel_masks[i] != 0) {
2599 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2600 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2601 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002602 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002604 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605 first = false;
2606 break;
2607 }
2608 }
2609 i++;
2610 }
2611 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2612 str = str_parms_to_str(reply);
2613 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002614 voice_extn_out_get_parameters(out, query, reply);
2615 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002616 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002617 free(str);
2618 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002619 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002621
Alexy Joseph62142aa2015-11-16 15:10:34 -08002622
2623 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2624 if (ret >= 0) {
2625 value[0] = '\0';
2626 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2627 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302628 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002629 } else {
2630 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302631 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002632 }
2633 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002634 if (str)
2635 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002636 str = str_parms_to_str(reply);
2637 }
2638
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002639 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2640 if (ret >= 0) {
2641 value[0] = '\0';
2642 i = 0;
2643 first = true;
2644 while (out->supported_formats[i] != 0) {
2645 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2646 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2647 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002648 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002649 }
2650 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2651 first = false;
2652 break;
2653 }
2654 }
2655 i++;
2656 }
2657 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002658 if (str)
2659 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002660 str = str_parms_to_str(reply);
2661 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002662
2663 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2664 if (ret >= 0) {
2665 value[0] = '\0';
2666 i = 0;
2667 first = true;
2668 while (out->supported_sample_rates[i] != 0) {
2669 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2670 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2671 if (!first) {
2672 strlcat(value, "|", sizeof(value));
2673 }
2674 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2675 first = false;
2676 break;
2677 }
2678 }
2679 i++;
2680 }
2681 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2682 if (str)
2683 free(str);
2684 str = str_parms_to_str(reply);
2685 }
2686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 str_parms_destroy(query);
2688 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002689 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 return str;
2691}
2692
2693static uint32_t out_get_latency(const struct audio_stream_out *stream)
2694{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002695 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002697 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698
Alexy Josephaa54c872014-12-03 02:46:47 -08002699 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002700 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002701 } else if (out->realtime) {
2702 // since the buffer won't be filled up faster than realtime,
2703 // return a smaller number
2704 if (out->config.rate)
2705 period_ms = (out->af_period_multiplier * out->config.period_size *
2706 1000) / (out->config.rate);
2707 else
2708 period_ms = 0;
2709 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002710 } else {
2711 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002712 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002713 }
2714
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302715 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002716 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717}
2718
2719static int out_set_volume(struct audio_stream_out *stream, float left,
2720 float right)
2721{
Eric Laurenta9024de2013-04-04 09:19:12 -07002722 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002723 int volume[2];
2724
Eric Laurenta9024de2013-04-04 09:19:12 -07002725 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2726 /* only take left channel into account: the API is for stereo anyway */
2727 out->muted = (left == 0.0f);
2728 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002729 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302730 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002731 /*
2732 * Set mute or umute on HDMI passthrough stream.
2733 * Only take left channel into account.
2734 * Mute is 0 and unmute 1
2735 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302736 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002737 } else {
2738 char mixer_ctl_name[128];
2739 struct audio_device *adev = out->dev;
2740 struct mixer_ctl *ctl;
2741 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002742 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002743
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002744 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2745 "Compress Playback %d Volume", pcm_device_id);
2746 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2747 if (!ctl) {
2748 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2749 __func__, mixer_ctl_name);
2750 return -EINVAL;
2751 }
2752 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2753 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2754 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2755 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002756 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002757 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 return -ENOSYS;
2760}
2761
2762static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2763 size_t bytes)
2764{
2765 struct stream_out *out = (struct stream_out *)stream;
2766 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302767 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002768 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002770 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302771
Naresh Tanniru80659832014-06-04 18:17:56 +05302772 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002773
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302774 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302775 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302776 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2777 pthread_mutex_unlock(&out->lock);
2778 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302779 } else {
2780 /* increase written size during SSR to avoid mismatch
2781 * with the written frames count in AF
2782 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302783 if (audio_bytes_per_sample(out->format) != 0)
2784 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302785 ALOGD(" %s: sound card is not active/SSR state", __func__);
2786 ret= -EIO;
2787 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302788 }
2789 }
2790
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302791 if (audio_extn_passthru_should_drop_data(out)) {
2792 ALOGD(" %s : Drop data as compress passthrough session is going on", __func__);
2793 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
2794 out_get_sample_rate(&out->stream.common));
2795 goto exit;
2796 }
2797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002799 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002800 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002801 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2802 ret = voice_extn_compress_voip_start_output_stream(out);
2803 else
2804 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002805 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002808 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 goto exit;
2810 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002811
2812 if (last_known_cal_step != -1) {
2813 ALOGD("%s: retry previous failed cal level set", __func__);
2814 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2815 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817
Ashish Jain81eb2a82015-05-13 10:52:34 +05302818 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002819 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302820 adev->is_channel_status_set = true;
2821 }
2822
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002823 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002824 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002825 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002826 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002827 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2828 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302829 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2830 ALOGD("copl(%p):send next track params in gapless", out);
2831 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2832 out->send_next_track_params = false;
2833 out->is_compr_metadata_avail = false;
2834 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002835 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302836 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302837 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002838
Ashish Jain83a6cc22016-06-28 14:34:17 +05302839 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302840 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302841 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302842 pthread_mutex_unlock(&out->lock);
2843 return -EINVAL;
2844 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302845 audio_format_t dst_format = out->hal_op_format;
2846 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302847
2848 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2849 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2850
Ashish Jain83a6cc22016-06-28 14:34:17 +05302851 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302852 dst_format,
2853 buffer,
2854 src_format,
2855 frames);
2856
Ashish Jain83a6cc22016-06-28 14:34:17 +05302857 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302858 bytes_to_write);
2859
2860 /*Convert written bytes in audio flinger format*/
2861 if (ret > 0)
2862 ret = ((ret * format_to_bitwidth_table[out->format]) /
2863 format_to_bitwidth_table[dst_format]);
2864 }
2865 } else
2866 ret = compress_write(out->compr, buffer, bytes);
2867
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302868 if (ret < 0)
2869 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302870 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002871 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302872 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302874 } else if (-ENETRESET == ret) {
2875 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2876 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2877 pthread_mutex_unlock(&out->lock);
2878 out_standby(&out->stream.common);
2879 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 }
Ashish Jain5106d362016-05-11 19:23:33 +05302881 if ( ret == (ssize_t)bytes && !out->non_blocking)
2882 out->written += bytes;
2883
Naresh Tanniru80659832014-06-04 18:17:56 +05302884 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002886 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887 out->playback_started = 1;
2888 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002889
2890 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2891 popcount(out->channel_mask),
2892 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 }
2894 pthread_mutex_unlock(&out->lock);
2895 return ret;
2896 } else {
2897 if (out->pcm) {
2898 if (out->muted)
2899 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002900
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302901 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002902
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002903 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002904
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002905 if (out->config.rate)
2906 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2907 out->config.rate;
2908
2909 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2910
2911 request_out_focus(out, ns);
2912
2913 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002914 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002915 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302916 out->convert_buffer != NULL) {
2917
2918 memcpy_by_audio_format(out->convert_buffer,
2919 out->hal_op_format,
2920 buffer,
2921 out->hal_ip_format,
2922 out->config.period_size * out->config.channels);
2923
2924 ret = pcm_write(out->pcm, out->convert_buffer,
2925 (out->config.period_size *
2926 out->config.channels *
2927 format_to_bitwidth_table[out->hal_op_format]));
2928 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002929 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302930 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002931
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002932 release_out_focus(out);
2933
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302934 if (ret < 0)
2935 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302936 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2937 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2938 else
2939 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 }
2942
2943exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302944 /* ToDo: There may be a corner case when SSR happens back to back during
2945 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302946 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302947 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302948 }
2949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 pthread_mutex_unlock(&out->lock);
2951
2952 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002953 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002954 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302955 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302956 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302957 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302958 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302959 out->standby = true;
2960 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002961 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302962 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302963 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964 }
2965 return bytes;
2966}
2967
2968static int out_get_render_position(const struct audio_stream_out *stream,
2969 uint32_t *dsp_frames)
2970{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302972 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002973
2974 if (dsp_frames == NULL)
2975 return -EINVAL;
2976
2977 *dsp_frames = 0;
2978 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002979 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302980
2981 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2982 * this operation and adev_close_output_stream(where out gets reset).
2983 */
2984 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2985 *dsp_frames = get_actual_pcm_frames_rendered(out);
2986 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2987 return 0;
2988 }
2989
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002990 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302991 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302992 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002993 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302994 if (ret < 0)
2995 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302997 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002998 }
2999 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303000 if (-ENETRESET == ret) {
3001 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3002 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3003 return -EINVAL;
3004 } else if(ret < 0) {
3005 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3006 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303007 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3008 /*
3009 * Handle corner case where compress session is closed during SSR
3010 * and timestamp is queried
3011 */
3012 ALOGE(" ERROR: sound card not active, return error");
3013 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303014 } else {
3015 return 0;
3016 }
Zhou Song32a556e2015-05-05 10:46:56 +08003017 } else if (audio_is_linear_pcm(out->format)) {
3018 *dsp_frames = out->written;
3019 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 } else
3021 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022}
3023
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003024static int out_add_audio_effect(const struct audio_stream *stream __unused,
3025 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026{
3027 return 0;
3028}
3029
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003030static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3031 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032{
3033 return 0;
3034}
3035
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003036static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3037 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038{
3039 return -EINVAL;
3040}
3041
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003042static int out_get_presentation_position(const struct audio_stream_out *stream,
3043 uint64_t *frames, struct timespec *timestamp)
3044{
3045 struct stream_out *out = (struct stream_out *)stream;
3046 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003047 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003048
Ashish Jain5106d362016-05-11 19:23:33 +05303049 /* below piece of code is not guarded against any lock because audioFliner serializes
3050 * this operation and adev_close_output_stream( where out gets reset).
3051 */
3052 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3053 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3054 *frames = get_actual_pcm_frames_rendered(out);
3055 /* this is the best we can do */
3056 clock_gettime(CLOCK_MONOTONIC, timestamp);
3057 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3058 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3059 return 0;
3060 }
3061
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003062 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003063
Ashish Jain5106d362016-05-11 19:23:33 +05303064 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3065 ret = compress_get_tstamp(out->compr, &dsp_frames,
3066 &out->sample_rate);
3067 ALOGVV("%s rendered frames %ld sample_rate %d",
3068 __func__, dsp_frames, out->sample_rate);
3069 *frames = dsp_frames;
3070 if (ret < 0)
3071 ret = -errno;
3072 if (-ENETRESET == ret) {
3073 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3074 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3075 ret = -EINVAL;
3076 } else
3077 ret = 0;
3078 /* this is the best we can do */
3079 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003080 } else {
3081 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003082 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003083 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3084 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003085 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003086 // This adjustment accounts for buffering after app processor.
3087 // It is based on estimated DSP latency per use case, rather than exact.
3088 signed_frames -=
3089 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3090
Eric Laurent949a0892013-09-20 09:20:13 -07003091 // It would be unusual for this value to be negative, but check just in case ...
3092 if (signed_frames >= 0) {
3093 *frames = signed_frames;
3094 ret = 0;
3095 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003096 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303097 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3098 *frames = out->written;
3099 clock_gettime(CLOCK_MONOTONIC, timestamp);
3100 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003101 }
3102 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003103 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003104 return ret;
3105}
3106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107static int out_set_callback(struct audio_stream_out *stream,
3108 stream_callback_t callback, void *cookie)
3109{
3110 struct stream_out *out = (struct stream_out *)stream;
3111
3112 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003113 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003114 out->offload_callback = callback;
3115 out->offload_cookie = cookie;
3116 pthread_mutex_unlock(&out->lock);
3117 return 0;
3118}
3119
3120static int out_pause(struct audio_stream_out* stream)
3121{
3122 struct stream_out *out = (struct stream_out *)stream;
3123 int status = -ENOSYS;
3124 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003125 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003126 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003127 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303129 struct audio_device *adev = out->dev;
3130 int snd_scard_state = get_snd_card_state(adev);
3131
3132 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3133 status = compress_pause(out->compr);
3134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003136
Mingming Yin21854652016-04-13 11:54:02 -07003137 if (audio_extn_passthru_is_active()) {
3138 ALOGV("offload use case, pause passthru");
3139 audio_extn_passthru_on_pause(out);
3140 }
3141
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303142 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003143 audio_extn_dts_notify_playback_state(out->usecase, 0,
3144 out->sample_rate, popcount(out->channel_mask),
3145 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 }
3147 pthread_mutex_unlock(&out->lock);
3148 }
3149 return status;
3150}
3151
3152static int out_resume(struct audio_stream_out* stream)
3153{
3154 struct stream_out *out = (struct stream_out *)stream;
3155 int status = -ENOSYS;
3156 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003157 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003158 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003159 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003160 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003161 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303162 struct audio_device *adev = out->dev;
3163 int snd_scard_state = get_snd_card_state(adev);
3164
Mingming Yin21854652016-04-13 11:54:02 -07003165 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3166 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3167 pthread_mutex_lock(&out->dev->lock);
3168 ALOGV("offload resume, check and set hdmi backend again");
3169 check_and_set_hdmi_backend(out);
3170 pthread_mutex_unlock(&out->dev->lock);
3171 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303172 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003173 }
3174 if (!status) {
3175 out->offload_state = OFFLOAD_STATE_PLAYING;
3176 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303177 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003178 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3179 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 }
3181 pthread_mutex_unlock(&out->lock);
3182 }
3183 return status;
3184}
3185
3186static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3187{
3188 struct stream_out *out = (struct stream_out *)stream;
3189 int status = -ENOSYS;
3190 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003191 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003192 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3194 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3195 else
3196 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3197 pthread_mutex_unlock(&out->lock);
3198 }
3199 return status;
3200}
3201
3202static int out_flush(struct audio_stream_out* stream)
3203{
3204 struct stream_out *out = (struct stream_out *)stream;
3205 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003206 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003207 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003208 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303210 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003212 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003213 return 0;
3214 }
3215 return -ENOSYS;
3216}
3217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218/** audio_stream_in implementation **/
3219static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3220{
3221 struct stream_in *in = (struct stream_in *)stream;
3222
3223 return in->config.rate;
3224}
3225
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003226static int in_set_sample_rate(struct audio_stream *stream __unused,
3227 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228{
3229 return -ENOSYS;
3230}
3231
3232static size_t in_get_buffer_size(const struct audio_stream *stream)
3233{
3234 struct stream_in *in = (struct stream_in *)stream;
3235
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003236 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3237 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003238 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3239 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003240
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003241 return in->config.period_size * in->af_period_multiplier *
3242 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243}
3244
3245static uint32_t in_get_channels(const struct audio_stream *stream)
3246{
3247 struct stream_in *in = (struct stream_in *)stream;
3248
3249 return in->channel_mask;
3250}
3251
3252static audio_format_t in_get_format(const struct audio_stream *stream)
3253{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003254 struct stream_in *in = (struct stream_in *)stream;
3255
3256 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257}
3258
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003259static int in_set_format(struct audio_stream *stream __unused,
3260 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261{
3262 return -ENOSYS;
3263}
3264
3265static int in_standby(struct audio_stream *stream)
3266{
3267 struct stream_in *in = (struct stream_in *)stream;
3268 struct audio_device *adev = in->dev;
3269 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303270 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3271 stream, in->usecase, use_case_table[in->usecase]);
3272
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003273 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003274 if (!in->standby && in->is_st_session) {
3275 ALOGD("%s: sound trigger pcm stop lab", __func__);
3276 audio_extn_sound_trigger_stop_lab(in);
3277 in->standby = 1;
3278 }
3279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003281 if (adev->adm_deregister_stream)
3282 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3283
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003284 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003286 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3287 voice_extn_compress_voip_close_input_stream(stream);
3288 ALOGD("VOIP input entered standby");
3289 } else {
3290 if (in->pcm) {
3291 pcm_close(in->pcm);
3292 in->pcm = NULL;
3293 }
3294 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003295 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003296 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 }
3298 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003299 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 return status;
3301}
3302
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003303static int in_dump(const struct audio_stream *stream __unused,
3304 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305{
3306 return 0;
3307}
3308
3309static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3310{
3311 struct stream_in *in = (struct stream_in *)stream;
3312 struct audio_device *adev = in->dev;
3313 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003315 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303317 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 parms = str_parms_create_str(kvpairs);
3319
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303320 if (!parms)
3321 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003322 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003323 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003324
3325 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3326 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 val = atoi(value);
3328 /* no audio source uses val == 0 */
3329 if ((in->source != val) && (val != 0)) {
3330 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003331 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3332 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3333 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003334 (in->config.rate == 8000 || in->config.rate == 16000 ||
3335 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003336 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003337 err = voice_extn_compress_voip_open_input_stream(in);
3338 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003339 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003340 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003341 }
3342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 }
3344 }
3345
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003346 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3347 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003349 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 in->device = val;
3351 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003352 if (!in->standby && !in->is_st_session) {
3353 ALOGV("update input routing change");
3354 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003355 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003356 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 }
3358 }
3359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003361 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362
3363 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303364error:
Eric Laurent994a6932013-07-17 11:51:42 -07003365 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 return ret;
3367}
3368
3369static char* in_get_parameters(const struct audio_stream *stream,
3370 const char *keys)
3371{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003372 struct stream_in *in = (struct stream_in *)stream;
3373 struct str_parms *query = str_parms_create_str(keys);
3374 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003375 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003376
3377 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003378 if (reply) {
3379 str_parms_destroy(reply);
3380 }
3381 if (query) {
3382 str_parms_destroy(query);
3383 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003384 ALOGE("in_get_parameters: failed to create query or reply");
3385 return NULL;
3386 }
3387
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003388 ALOGV("%s: enter: keys - %s", __func__, keys);
3389
3390 voice_extn_in_get_parameters(in, query, reply);
3391
3392 str = str_parms_to_str(reply);
3393 str_parms_destroy(query);
3394 str_parms_destroy(reply);
3395
3396 ALOGV("%s: exit: returns - %s", __func__, str);
3397 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398}
3399
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003400static int in_set_gain(struct audio_stream_in *stream __unused,
3401 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402{
3403 return 0;
3404}
3405
3406static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3407 size_t bytes)
3408{
3409 struct stream_in *in = (struct stream_in *)stream;
3410 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303411 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303412 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303413 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003415 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303416
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003417 if (in->is_st_session) {
3418 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3419 /* Read from sound trigger HAL */
3420 audio_extn_sound_trigger_read(in, buffer, bytes);
3421 pthread_mutex_unlock(&in->lock);
3422 return bytes;
3423 }
3424
Ashish Jainbbce4322016-02-16 13:25:27 +05303425 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003426 ALOGD(" %s: sound card is not active/SSR state", __func__);
3427 ret= -EIO;;
3428 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303429 }
3430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003432 pthread_mutex_lock(&adev->lock);
3433 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3434 ret = voice_extn_compress_voip_start_input_stream(in);
3435 else
3436 ret = start_input_stream(in);
3437 pthread_mutex_unlock(&adev->lock);
3438 if (ret != 0) {
3439 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 }
3441 in->standby = 0;
3442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003443
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003444 // what's the duration requested by the client?
3445 long ns = 0;
3446
3447 if (in->config.rate)
3448 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3449 in->config.rate;
3450
3451 request_in_focus(in, ns);
3452 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303455 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003456 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303457 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003458 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003459 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003460 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303461 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003462 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303463 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3464 if (bytes % 4 == 0) {
3465 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3466 int_buf_stream = buffer;
3467 for (size_t itt=0; itt < bytes/4 ; itt++) {
3468 int_buf_stream[itt] >>= 8;
3469 }
3470 } else {
3471 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3472 ret = -EINVAL;
3473 goto exit;
3474 }
3475 } if (ret < 0) {
3476 ret = -errno;
3477 }
3478 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479 }
3480
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003481 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003483 /*
3484 * Instead of writing zeroes here, we could trust the hardware
3485 * to always provide zeroes when muted.
3486 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303487 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3488 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 memset(buffer, 0, bytes);
3490
3491exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303492 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303493 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003494 if (-ENETRESET == ret)
3495 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497 pthread_mutex_unlock(&in->lock);
3498
3499 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303500 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303501 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303502 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303503 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303504 in->standby = true;
3505 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303506 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003508 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303509 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303510 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511 }
3512 return bytes;
3513}
3514
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003515static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516{
3517 return 0;
3518}
3519
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003520static int add_remove_audio_effect(const struct audio_stream *stream,
3521 effect_handle_t effect,
3522 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003524 struct stream_in *in = (struct stream_in *)stream;
3525 int status = 0;
3526 effect_descriptor_t desc;
3527
3528 status = (*effect)->get_descriptor(effect, &desc);
3529 if (status != 0)
3530 return status;
3531
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003532 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003533 pthread_mutex_lock(&in->dev->lock);
3534 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3535 in->enable_aec != enable &&
3536 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3537 in->enable_aec = enable;
3538 if (!in->standby)
3539 select_devices(in->dev, in->usecase);
3540 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003541 if (in->enable_ns != enable &&
3542 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3543 in->enable_ns = enable;
3544 if (!in->standby)
3545 select_devices(in->dev, in->usecase);
3546 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003547 pthread_mutex_unlock(&in->dev->lock);
3548 pthread_mutex_unlock(&in->lock);
3549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 return 0;
3551}
3552
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003553static int in_add_audio_effect(const struct audio_stream *stream,
3554 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555{
Eric Laurent994a6932013-07-17 11:51:42 -07003556 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003557 return add_remove_audio_effect(stream, effect, true);
3558}
3559
3560static int in_remove_audio_effect(const struct audio_stream *stream,
3561 effect_handle_t effect)
3562{
Eric Laurent994a6932013-07-17 11:51:42 -07003563 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003564 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565}
3566
3567static int adev_open_output_stream(struct audio_hw_device *dev,
3568 audio_io_handle_t handle,
3569 audio_devices_t devices,
3570 audio_output_flags_t flags,
3571 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003572 struct audio_stream_out **stream_out,
3573 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574{
3575 struct audio_device *adev = (struct audio_device *)dev;
3576 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303577 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003578 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303581
3582 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3583 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003584 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303585 return -EINVAL;
3586 }
3587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003588 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3589
Mingming Yin3a941d42016-02-17 18:08:05 -08003590 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3591 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303592 devices, flags, &out->stream);
3593
3594
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003595 if (!out) {
3596 return -ENOMEM;
3597 }
3598
Haynes Mathew George204045b2015-02-25 20:32:03 -08003599 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003600 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003601 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603 if (devices == AUDIO_DEVICE_NONE)
3604 devices = AUDIO_DEVICE_OUT_SPEAKER;
3605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 out->flags = flags;
3607 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003608 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003609 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003610 out->sample_rate = config->sample_rate;
3611 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3612 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003613 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003614 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003615 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303616 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617
Mingming Yin3a941d42016-02-17 18:08:05 -08003618 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3619 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3620 pthread_mutex_lock(&adev->lock);
3621 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3622 ret = read_hdmi_sink_caps(out);
3623 pthread_mutex_unlock(&adev->lock);
3624 if (ret != 0) {
3625 if (ret == -ENOSYS) {
3626 /* ignore and go with default */
3627 ret = 0;
3628 } else {
3629 ALOGE("error reading hdmi sink caps");
3630 goto error_open;
3631 }
3632 }
3633 }
3634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003636 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303637 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3638 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003639 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3640 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3641
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003642 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003643 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3644 /*
3645 * Do not handle stereo output in Multi-channel cases
3646 * Stereo case is handled in normal playback path
3647 */
3648 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3649 ret = AUDIO_CHANNEL_OUT_STEREO;
3650 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003651
3652 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3653 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003654 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003655 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003656 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003657
3658 if (config->sample_rate == 0)
3659 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3660 if (config->channel_mask == 0)
3661 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003662 if (config->format == 0)
3663 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003664
3665 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003667 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3669 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003671 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003673 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3674 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003675 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003676 ret = voice_extn_compress_voip_open_output_stream(out);
3677 if (ret != 0) {
3678 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3679 __func__, ret);
3680 goto error_open;
3681 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003682 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3683 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3684
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003685 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3686 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3687 ALOGE("%s: Unsupported Offload information", __func__);
3688 ret = -EINVAL;
3689 goto error_open;
3690 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003691
Mingming Yin3a941d42016-02-17 18:08:05 -08003692 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003693 if(config->offload_info.format == 0)
3694 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003695 if (config->offload_info.sample_rate == 0)
3696 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003697 }
3698
Mingming Yin90310102013-11-13 16:57:00 -08003699 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303700 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003701 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003702 ret = -EINVAL;
3703 goto error_open;
3704 }
3705
3706 out->compr_config.codec = (struct snd_codec *)
3707 calloc(1, sizeof(struct snd_codec));
3708
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003709 if (!out->compr_config.codec) {
3710 ret = -ENOMEM;
3711 goto error_open;
3712 }
3713
vivek mehta0ea887a2015-08-26 14:01:20 -07003714 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303715 out->stream.pause = out_pause;
3716 out->stream.flush = out_flush;
3717 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003718 out->usecase = get_offload_usecase(adev, true);
3719 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003720 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003721 out->stream.set_callback = out_set_callback;
3722 out->stream.pause = out_pause;
3723 out->stream.resume = out_resume;
3724 out->stream.drain = out_drain;
3725 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003726 out->usecase = get_offload_usecase(adev, false);
3727 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003728 }
vivek mehta446c3962015-09-14 10:57:35 -07003729
3730 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003731 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3732 config->format == 0 && config->sample_rate == 0 &&
3733 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003734 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003735 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3736 } else {
3737 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3738 ret = -EEXIST;
3739 goto error_open;
3740 }
vivek mehta446c3962015-09-14 10:57:35 -07003741 }
3742
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003743 if (config->offload_info.channel_mask)
3744 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003745 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003746 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003747 config->offload_info.channel_mask = config->channel_mask;
3748 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003749 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003750 out->sample_rate = config->offload_info.sample_rate;
3751
Mingming Yin3ee55c62014-08-04 14:23:35 -07003752 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003753
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303754 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3755 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3756 audio_extn_dolby_send_ddp_endp_params(adev);
3757 audio_extn_dolby_set_dmid(adev);
3758 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003759
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003760 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003761 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 out->compr_config.codec->bit_rate =
3763 config->offload_info.bit_rate;
3764 out->compr_config.codec->ch_in =
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003765 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003766 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303767 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003768 /*TODO: Do we need to change it for passthrough */
3769 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003770
Manish Dewangana6fc5442015-08-24 20:30:31 +05303771 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3772 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3773 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3774 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303775
3776 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3777 AUDIO_FORMAT_PCM) {
3778
3779 /*Based on platform support, configure appropriate alsa format for corresponding
3780 *hal input format.
3781 */
3782 out->compr_config.codec->format = hal_format_to_alsa(
3783 config->offload_info.format);
3784
Ashish Jain83a6cc22016-06-28 14:34:17 +05303785 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303786 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303787 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303788
3789 /*for direct PCM playback populate bit_width based on selected alsa format as
3790 *hal input format and alsa format might differ based on platform support.
3791 */
3792 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303793 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303794
3795 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3796
3797 /* Check if alsa session is configured with the same format as HAL input format,
3798 * if not then derive correct fragment size needed to accomodate the
3799 * conversion of HAL input format to alsa format.
3800 */
3801 audio_extn_utils_update_direct_pcm_fragment_size(out);
3802
3803 /*if hal input and output fragment size is different this indicates HAL input format is
3804 *not same as the alsa format
3805 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303806 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303807 /*Allocate a buffer to convert input data to the alsa configured format.
3808 *size of convert buffer is equal to the size required to hold one fragment size
3809 *worth of pcm data, this is because flinger does not write more than fragment_size
3810 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303811 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3812 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303813 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3814 ret = -ENOMEM;
3815 goto error_open;
3816 }
3817 }
3818 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3819 out->compr_config.fragment_size =
3820 audio_extn_passthru_get_buffer_size(&config->offload_info);
3821 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3822 } else {
3823 out->compr_config.fragment_size =
3824 platform_get_compress_offload_buffer_size(&config->offload_info);
3825 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3826 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003827
Amit Shekhar6f461b12014-08-01 14:52:58 -07003828 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303829 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003830
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003831 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3832 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003833
Alexy Josephaa54c872014-12-03 02:46:47 -08003834
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003835 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303836 out->send_next_track_params = false;
3837 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003838 out->offload_state = OFFLOAD_STATE_IDLE;
3839 out->playback_started = 0;
3840
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003841 audio_extn_dts_create_state_notifier_node(out->usecase);
3842
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003843 create_offload_callback_thread(out);
3844 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3845 __func__, config->offload_info.version,
3846 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303847
3848 /* Disable gapless if any of the following is true
3849 * passthrough playback
3850 * AV playback
3851 * Direct PCM playback
3852 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303853 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303854 config->offload_info.has_video ||
3855 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3856 check_and_set_gapless_mode(adev, false);
3857 } else
3858 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003859
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303860 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003861 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3862 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003863 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303864 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003865 if (ret != 0) {
3866 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3867 __func__, ret);
3868 goto error_open;
3869 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003870 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3871 if (config->sample_rate == 0)
3872 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3873 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3874 config->sample_rate != 8000) {
3875 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3876 ret = -EINVAL;
3877 goto error_open;
3878 }
3879 out->sample_rate = config->sample_rate;
3880 out->config.rate = config->sample_rate;
3881 if (config->format == AUDIO_FORMAT_DEFAULT)
3882 config->format = AUDIO_FORMAT_PCM_16_BIT;
3883 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3884 config->format = AUDIO_FORMAT_PCM_16_BIT;
3885 ret = -EINVAL;
3886 goto error_open;
3887 }
3888 out->format = config->format;
3889 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3890 out->config = pcm_config_afe_proxy_playback;
3891 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003892 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303893 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3894 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003895 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3896 out->flags);
3897 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303898 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3899 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3900 out->config = pcm_config_low_latency;
3901 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3902 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3903 out->config = pcm_config_deep_buffer;
3904 } else {
3905 /* primary path is the default path selected if no other outputs are available/suitable */
3906 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3907 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3908 }
3909 out->hal_ip_format = format = out->format;
3910 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3911 out->hal_op_format = pcm_format_to_hal(out->config.format);
3912 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3913 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003914 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303915 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3916 if (out->hal_ip_format != out->hal_op_format) {
3917 uint32_t buffer_size = out->config.period_size *
3918 format_to_bitwidth_table[out->hal_op_format] *
3919 out->config.channels;
3920 out->convert_buffer = calloc(1, buffer_size);
3921 if (out->convert_buffer == NULL){
3922 ALOGE("Allocation failed for convert buffer for size %d",
3923 out->compr_config.fragment_size);
3924 ret = -ENOMEM;
3925 goto error_open;
3926 }
3927 ALOGD("Convert buffer allocated of size %d", buffer_size);
3928 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929 }
3930
Ashish Jain83a6cc22016-06-28 14:34:17 +05303931 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3932 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3933
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003934 /* TODO remove this hardcoding and check why width is zero*/
3935 if (out->bit_width == 0)
3936 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003937 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3938 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003939 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303940 out->bit_width, out->channel_mask,
3941 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003942 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3943 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3944 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003945 if(adev->primary_output == NULL)
3946 adev->primary_output = out;
3947 else {
3948 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003949 ret = -EEXIST;
3950 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003951 }
3952 }
3953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 /* Check if this usecase is already existing */
3955 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003956 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3957 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003958 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003960 ret = -EEXIST;
3961 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 }
3963 pthread_mutex_unlock(&adev->lock);
3964
3965 out->stream.common.get_sample_rate = out_get_sample_rate;
3966 out->stream.common.set_sample_rate = out_set_sample_rate;
3967 out->stream.common.get_buffer_size = out_get_buffer_size;
3968 out->stream.common.get_channels = out_get_channels;
3969 out->stream.common.get_format = out_get_format;
3970 out->stream.common.set_format = out_set_format;
3971 out->stream.common.standby = out_standby;
3972 out->stream.common.dump = out_dump;
3973 out->stream.common.set_parameters = out_set_parameters;
3974 out->stream.common.get_parameters = out_get_parameters;
3975 out->stream.common.add_audio_effect = out_add_audio_effect;
3976 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3977 out->stream.get_latency = out_get_latency;
3978 out->stream.set_volume = out_set_volume;
3979 out->stream.write = out_write;
3980 out->stream.get_render_position = out_get_render_position;
3981 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003982 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003984 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003985 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003986 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003987 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988
3989 config->format = out->stream.common.get_format(&out->stream.common);
3990 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3991 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3992
3993 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303994 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003995 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003996
3997 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3998 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3999 popcount(out->channel_mask), out->playback_started);
4000
Eric Laurent994a6932013-07-17 11:51:42 -07004001 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004003
4004error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304005 if (out->convert_buffer)
4006 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004007 free(out);
4008 *stream_out = NULL;
4009 ALOGD("%s: exit: ret %d", __func__, ret);
4010 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011}
4012
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004013static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014 struct audio_stream_out *stream)
4015{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004016 struct stream_out *out = (struct stream_out *)stream;
4017 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004018 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004019
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304020 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4021
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004022 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304023 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004024 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304025 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004026 if(ret != 0)
4027 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4028 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004029 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004030 out_standby(&stream->common);
4031
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004032 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004033 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004034 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004035 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 if (out->compr_config.codec != NULL)
4037 free(out->compr_config.codec);
4038 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004039
Ashish Jain83a6cc22016-06-28 14:34:17 +05304040 if (out->convert_buffer != NULL) {
4041 free(out->convert_buffer);
4042 out->convert_buffer = NULL;
4043 }
4044
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004045 if (adev->voice_tx_output == out)
4046 adev->voice_tx_output = NULL;
4047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048 pthread_cond_destroy(&out->cond);
4049 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004051 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052}
4053
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004054static void close_compress_sessions(struct audio_device *adev)
4055{
Mingming Yin7b762e72015-03-04 13:47:32 -08004056 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304057 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004058 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004059 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304060
4061 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004062 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304063 if (is_offload_usecase(usecase->id)) {
4064 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004065 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4066 out = usecase->stream.out;
4067 pthread_mutex_unlock(&adev->lock);
4068 out_standby(&out->stream.common);
4069 pthread_mutex_lock(&adev->lock);
4070 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304071 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004072 }
4073 pthread_mutex_unlock(&adev->lock);
4074}
4075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004076static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4077{
4078 struct audio_device *adev = (struct audio_device *)dev;
4079 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004081 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004082 int ret;
4083 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004085 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304088 if (!parms)
4089 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004090 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4091 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304092 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304093 if (strstr(snd_card_status, "OFFLINE")) {
4094 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304095 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004096 //close compress sessions on OFFLINE status
4097 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304098 } else if (strstr(snd_card_status, "ONLINE")) {
4099 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304100 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004101 //send dts hpx license if enabled
4102 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304103 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304104 }
4105
4106 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004107 status = voice_set_parameters(adev, parms);
4108 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004109 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004111 status = platform_set_parameters(adev->platform, parms);
4112 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004113 goto done;
4114
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004115 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4116 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004117 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4119 adev->bluetooth_nrec = true;
4120 else
4121 adev->bluetooth_nrec = false;
4122 }
4123
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004124 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4125 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004126 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4127 adev->screen_off = false;
4128 else
4129 adev->screen_off = true;
4130 }
4131
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004132 ret = str_parms_get_int(parms, "rotation", &val);
4133 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004134 bool reverse_speakers = false;
4135 switch(val) {
4136 // FIXME: note that the code below assumes that the speakers are in the correct placement
4137 // relative to the user when the device is rotated 90deg from its default rotation. This
4138 // assumption is device-specific, not platform-specific like this code.
4139 case 270:
4140 reverse_speakers = true;
4141 break;
4142 case 0:
4143 case 90:
4144 case 180:
4145 break;
4146 default:
4147 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004148 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004149 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004150 if (status == 0) {
4151 if (adev->speaker_lr_swap != reverse_speakers) {
4152 adev->speaker_lr_swap = reverse_speakers;
4153 // only update the selected device if there is active pcm playback
4154 struct audio_usecase *usecase;
4155 struct listnode *node;
4156 list_for_each(node, &adev->usecase_list) {
4157 usecase = node_to_item(node, struct audio_usecase, list);
4158 if (usecase->type == PCM_PLAYBACK) {
4159 select_devices(adev, usecase->id);
4160 break;
4161 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004162 }
4163 }
4164 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004165 }
4166
Mingming Yin514a8bc2014-07-29 15:22:21 -07004167 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4168 if (ret >= 0) {
4169 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4170 adev->bt_wb_speech_enabled = true;
4171 else
4172 adev->bt_wb_speech_enabled = false;
4173 }
4174
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004175 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4176 if (ret >= 0) {
4177 val = atoi(value);
4178 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4179 ALOGV("cache new edid");
4180 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004181 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4182 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004183 /*
4184 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4185 * Per AudioPolicyManager, USB device is higher priority than WFD.
4186 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4187 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4188 * starting voice call on USB
4189 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004190 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4191 if (ret >= 0) {
4192 audio_extn_usb_add_device(val, atoi(value));
4193 }
vivek mehta344576a2016-04-12 18:56:03 -07004194 ALOGV("detected USB connect .. disable proxy");
4195 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004196 }
4197 }
4198
4199 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4200 if (ret >= 0) {
4201 val = atoi(value);
4202 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4203 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004204 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004205 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4206 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4207 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4208 if (ret >= 0) {
4209 audio_extn_usb_remove_device(val, atoi(value));
4210 }
vivek mehta344576a2016-04-12 18:56:03 -07004211 ALOGV("detected USB disconnect .. enable proxy");
4212 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004213 }
4214 }
4215
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004216 audio_extn_set_parameters(adev, parms);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304217 // reconfigure should be done only after updating a2dpstate in audio extn
4218 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4219 if (ret >= 0) {
4220 struct audio_usecase *usecase;
4221 struct listnode *node;
4222 list_for_each(node, &adev->usecase_list) {
4223 usecase = node_to_item(node, struct audio_usecase, list);
4224 if ((usecase->type == PCM_PLAYBACK) &&
4225 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4226 ALOGD("reconfigure a2dp... forcing device switch");
4227 //force device switch to re configure encoder
4228 select_devices(adev, usecase->id);
4229 break;
4230 }
4231 }
4232 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004233
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004234done:
4235 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004236 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304237error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004238 ALOGV("%s: exit with code(%d)", __func__, status);
4239 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240}
4241
4242static char* adev_get_parameters(const struct audio_hw_device *dev,
4243 const char *keys)
4244{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004245 struct audio_device *adev = (struct audio_device *)dev;
4246 struct str_parms *reply = str_parms_create();
4247 struct str_parms *query = str_parms_create_str(keys);
4248 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304249 char value[256] = {0};
4250 int ret = 0;
4251
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004252 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004253 if (reply) {
4254 str_parms_destroy(reply);
4255 }
4256 if (query) {
4257 str_parms_destroy(query);
4258 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004259 ALOGE("adev_get_parameters: failed to create query or reply");
4260 return NULL;
4261 }
4262
Naresh Tannirud7205b62014-06-20 02:54:48 +05304263 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4264 sizeof(value));
4265 if (ret >=0) {
4266 int val = 1;
4267 pthread_mutex_lock(&adev->snd_card_status.lock);
4268 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4269 val = 0;
4270 pthread_mutex_unlock(&adev->snd_card_status.lock);
4271 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4272 goto exit;
4273 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004274
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004275 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004276 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004277 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004278 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304279 pthread_mutex_unlock(&adev->lock);
4280
Naresh Tannirud7205b62014-06-20 02:54:48 +05304281exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004282 str = str_parms_to_str(reply);
4283 str_parms_destroy(query);
4284 str_parms_destroy(reply);
4285
4286 ALOGV("%s: exit: returns - %s", __func__, str);
4287 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004288}
4289
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004290static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291{
4292 return 0;
4293}
4294
4295static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4296{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004297 int ret;
4298 struct audio_device *adev = (struct audio_device *)dev;
4299 pthread_mutex_lock(&adev->lock);
4300 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004301 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004302 pthread_mutex_unlock(&adev->lock);
4303 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304}
4305
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004306static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4307 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004308{
4309 return -ENOSYS;
4310}
4311
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004312static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4313 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314{
4315 return -ENOSYS;
4316}
4317
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004318static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4319 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320{
4321 return -ENOSYS;
4322}
4323
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004324static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4325 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326{
4327 return -ENOSYS;
4328}
4329
4330static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4331{
4332 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 pthread_mutex_lock(&adev->lock);
4335 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004336 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004338 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004339 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004340 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004341 adev->current_call_output = NULL;
4342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343 }
4344 pthread_mutex_unlock(&adev->lock);
4345 return 0;
4346}
4347
4348static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4349{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004350 int ret;
4351
4352 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004353 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004354 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4355 pthread_mutex_unlock(&adev->lock);
4356
4357 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358}
4359
4360static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4361{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004362 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363 return 0;
4364}
4365
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004366static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367 const struct audio_config *config)
4368{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004369 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004371 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4372 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373}
4374
4375static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004376 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 audio_devices_t devices,
4378 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004379 struct audio_stream_in **stream_in,
4380 audio_input_flags_t flags __unused,
4381 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004382 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383{
4384 struct audio_device *adev = (struct audio_device *)dev;
4385 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004386 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004387 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004388 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304391 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4392 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304394 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395
4396 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004397
4398 if (!in) {
4399 ALOGE("failed to allocate input stream");
4400 return -ENOMEM;
4401 }
4402
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304403 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304404 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4405 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004406 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004407 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 in->stream.common.get_sample_rate = in_get_sample_rate;
4410 in->stream.common.set_sample_rate = in_set_sample_rate;
4411 in->stream.common.get_buffer_size = in_get_buffer_size;
4412 in->stream.common.get_channels = in_get_channels;
4413 in->stream.common.get_format = in_get_format;
4414 in->stream.common.set_format = in_set_format;
4415 in->stream.common.standby = in_standby;
4416 in->stream.common.dump = in_dump;
4417 in->stream.common.set_parameters = in_set_parameters;
4418 in->stream.common.get_parameters = in_get_parameters;
4419 in->stream.common.add_audio_effect = in_add_audio_effect;
4420 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4421 in->stream.set_gain = in_set_gain;
4422 in->stream.read = in_read;
4423 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4424
4425 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004426 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004428 in->standby = 1;
4429 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004430 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004431 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432
4433 /* Update config params with the requested sample rate and channels */
4434 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004435 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4436 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4437 is_low_latency = true;
4438#if LOW_LATENCY_CAPTURE_USE_CASE
4439 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4440#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004441 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004442 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004443
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004444 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004445 if (in->realtime) {
4446 in->config = pcm_config_audio_capture_rt;
4447 in->sample_rate = in->config.rate;
4448 in->af_period_multiplier = af_period_multiplier;
4449 } else {
4450 in->config = pcm_config_audio_capture;
4451 in->config.rate = config->sample_rate;
4452 in->sample_rate = config->sample_rate;
4453 in->af_period_multiplier = 1;
4454 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304455 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004457 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304458 if (adev->mode != AUDIO_MODE_IN_CALL) {
4459 ret = -EINVAL;
4460 goto err_open;
4461 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004462 if (config->sample_rate == 0)
4463 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4464 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4465 config->sample_rate != 8000) {
4466 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4467 ret = -EINVAL;
4468 goto err_open;
4469 }
4470 if (config->format == AUDIO_FORMAT_DEFAULT)
4471 config->format = AUDIO_FORMAT_PCM_16_BIT;
4472 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4473 config->format = AUDIO_FORMAT_PCM_16_BIT;
4474 ret = -EINVAL;
4475 goto err_open;
4476 }
4477
4478 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4479 in->config = pcm_config_afe_proxy_record;
4480 in->config.channels = channel_count;
4481 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304482 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304483 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4484 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004485 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004486 audio_extn_compr_cap_format_supported(config->format) &&
4487 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004488 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004489 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304490 /* restrict 24 bit capture for unprocessed source only
4491 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4492 */
4493 if (config->format == AUDIO_FORMAT_DEFAULT) {
4494 config->format = AUDIO_FORMAT_PCM_16_BIT;
4495 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4496 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4497 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4498 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4499 bool ret_error = false;
4500 in->bit_width = 24;
4501 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4502 from HAL is 24_packed and 8_24
4503 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4504 24_packed return error indicating supported format is 24_packed
4505 *> In case of any other source requesting 24 bit or float return error
4506 indicating format supported is 16 bit only.
4507
4508 on error flinger will retry with supported format passed
4509 */
4510 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4511 (source != AUDIO_SOURCE_CAMCORDER)) {
4512 config->format = AUDIO_FORMAT_PCM_16_BIT;
4513 if( config->sample_rate > 48000)
4514 config->sample_rate = 48000;
4515 ret_error = true;
4516 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4517 in->config.format = PCM_FORMAT_S24_3LE;
4518 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4519 in->config.format = PCM_FORMAT_S24_LE;
4520 } else {
4521 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4522 ret_error = true;
4523 }
4524
4525 if (ret_error) {
4526 ret = -EINVAL;
4527 goto err_open;
4528 }
4529 }
4530
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004531 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004532 if (!in->realtime) {
4533 in->format = config->format;
4534 frame_size = audio_stream_in_frame_size(&in->stream);
4535 buffer_size = get_input_buffer_size(config->sample_rate,
4536 config->format,
4537 channel_count,
4538 is_low_latency);
4539 in->config.period_size = buffer_size / frame_size;
4540 }
4541
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004542 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4543 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4544 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004545 (in->config.rate == 8000 || in->config.rate == 16000 ||
4546 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004547 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4548 voice_extn_compress_voip_open_input_stream(in);
4549 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004550 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004552 /* This stream could be for sound trigger lab,
4553 get sound trigger pcm if present */
4554 audio_extn_sound_trigger_check_and_get_session(in);
4555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004557 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004558 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559
4560err_open:
4561 free(in);
4562 *stream_in = NULL;
4563 return ret;
4564}
4565
4566static void adev_close_input_stream(struct audio_hw_device *dev,
4567 struct audio_stream_in *stream)
4568{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004569 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004570 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004571 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304572
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304573 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004574
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304575 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004576 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304577
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004578 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304579 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004580 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304581 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004582 if (ret != 0)
4583 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4584 __func__, ret);
4585 } else
4586 in_standby(&stream->common);
4587
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004588 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004589 audio_extn_ssr_deinit();
4590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591
Mingming Yine62d7842013-10-25 16:26:03 -07004592 if(audio_extn_compr_cap_enabled() &&
4593 audio_extn_compr_cap_format_supported(in->config.format))
4594 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004595
Mingming Yinfd7607b2016-01-22 12:48:44 -08004596 if (in->is_st_session) {
4597 ALOGV("%s: sound trigger pcm stop lab", __func__);
4598 audio_extn_sound_trigger_stop_lab(in);
4599 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004600 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601 return;
4602}
4603
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004604static int adev_dump(const audio_hw_device_t *device __unused,
4605 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606{
4607 return 0;
4608}
4609
4610static int adev_close(hw_device_t *device)
4611{
4612 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004613
4614 if (!adev)
4615 return 0;
4616
4617 pthread_mutex_lock(&adev_init_lock);
4618
4619 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004620 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004621 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004622 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004623 audio_route_free(adev->audio_route);
4624 free(adev->snd_dev_ref_cnt);
4625 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004626 if (adev->adm_deinit)
4627 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004628 free(device);
4629 adev = NULL;
4630 }
4631 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 return 0;
4634}
4635
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004636/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4637 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4638 * just that it _might_ work.
4639 */
4640static int period_size_is_plausible_for_low_latency(int period_size)
4641{
4642 switch (period_size) {
4643 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004644 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004645 case 240:
4646 case 320:
4647 case 480:
4648 return 1;
4649 default:
4650 return 0;
4651 }
4652}
4653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654static int adev_open(const hw_module_t *module, const char *name,
4655 hw_device_t **device)
4656{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004657 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4659
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004660 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004661 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004662 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004663 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004664 ALOGD("%s: returning existing instance of adev", __func__);
4665 ALOGD("%s: exit", __func__);
4666 pthread_mutex_unlock(&adev_init_lock);
4667 return 0;
4668 }
4669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670 adev = calloc(1, sizeof(struct audio_device));
4671
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004672 if (!adev) {
4673 pthread_mutex_unlock(&adev_init_lock);
4674 return -ENOMEM;
4675 }
4676
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004677 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4680 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4681 adev->device.common.module = (struct hw_module_t *)module;
4682 adev->device.common.close = adev_close;
4683
4684 adev->device.init_check = adev_init_check;
4685 adev->device.set_voice_volume = adev_set_voice_volume;
4686 adev->device.set_master_volume = adev_set_master_volume;
4687 adev->device.get_master_volume = adev_get_master_volume;
4688 adev->device.set_master_mute = adev_set_master_mute;
4689 adev->device.get_master_mute = adev_get_master_mute;
4690 adev->device.set_mode = adev_set_mode;
4691 adev->device.set_mic_mute = adev_set_mic_mute;
4692 adev->device.get_mic_mute = adev_get_mic_mute;
4693 adev->device.set_parameters = adev_set_parameters;
4694 adev->device.get_parameters = adev_get_parameters;
4695 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4696 adev->device.open_output_stream = adev_open_output_stream;
4697 adev->device.close_output_stream = adev_close_output_stream;
4698 adev->device.open_input_stream = adev_open_input_stream;
4699 adev->device.close_input_stream = adev_close_input_stream;
4700 adev->device.dump = adev_dump;
4701
4702 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004704 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004705 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004708 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004709 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004710 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004711 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004712 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004713 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004714 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004715 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304716 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304717 adev->perf_lock_opts[0] = 0x101;
4718 adev->perf_lock_opts[1] = 0x20E;
4719 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304720
4721 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4722 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004724 adev->platform = platform_init(adev);
4725 if (!adev->platform) {
4726 free(adev->snd_dev_ref_cnt);
4727 free(adev);
4728 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4729 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004730 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004731 return -EINVAL;
4732 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004733
Naresh Tanniru4c630392014-05-12 01:05:52 +05304734 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4735
Eric Laurentc4aef752013-09-12 17:45:53 -07004736 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4737 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4738 if (adev->visualizer_lib == NULL) {
4739 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4740 } else {
4741 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4742 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004743 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004744 "visualizer_hal_start_output");
4745 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004746 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004747 "visualizer_hal_stop_output");
4748 }
4749 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004750 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004751 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004752
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004753 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4754 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4755 if (adev->offload_effects_lib == NULL) {
4756 ALOGE("%s: DLOPEN failed for %s", __func__,
4757 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4758 } else {
4759 ALOGV("%s: DLOPEN successful for %s", __func__,
4760 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4761 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304762 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004763 "offload_effects_bundle_hal_start_output");
4764 adev->offload_effects_stop_output =
4765 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4766 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004767 adev->offload_effects_set_hpx_state =
4768 (int (*)(bool))dlsym(adev->offload_effects_lib,
4769 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304770 adev->offload_effects_get_parameters =
4771 (void (*)(struct str_parms *, struct str_parms *))
4772 dlsym(adev->offload_effects_lib,
4773 "offload_effects_bundle_get_parameters");
4774 adev->offload_effects_set_parameters =
4775 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4776 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004777 }
4778 }
4779
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004780 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4781 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4782 if (adev->adm_lib == NULL) {
4783 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4784 } else {
4785 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4786 adev->adm_init = (adm_init_t)
4787 dlsym(adev->adm_lib, "adm_init");
4788 adev->adm_deinit = (adm_deinit_t)
4789 dlsym(adev->adm_lib, "adm_deinit");
4790 adev->adm_register_input_stream = (adm_register_input_stream_t)
4791 dlsym(adev->adm_lib, "adm_register_input_stream");
4792 adev->adm_register_output_stream = (adm_register_output_stream_t)
4793 dlsym(adev->adm_lib, "adm_register_output_stream");
4794 adev->adm_deregister_stream = (adm_deregister_stream_t)
4795 dlsym(adev->adm_lib, "adm_deregister_stream");
4796 adev->adm_request_focus = (adm_request_focus_t)
4797 dlsym(adev->adm_lib, "adm_request_focus");
4798 adev->adm_abandon_focus = (adm_abandon_focus_t)
4799 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004800 adev->adm_set_config = (adm_set_config_t)
4801 dlsym(adev->adm_lib, "adm_set_config");
4802 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4803 dlsym(adev->adm_lib, "adm_request_focus_v2");
4804 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4805 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4806 adev->adm_on_routing_change = (adm_on_routing_change_t)
4807 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004808 }
4809 }
4810
Mingming Yin514a8bc2014-07-29 15:22:21 -07004811 adev->bt_wb_speech_enabled = false;
4812
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004813 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814 *device = &adev->device.common;
4815
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004816 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4817 &adev->streams_output_cfg_list);
4818
Kiran Kandi910e1862013-10-29 13:29:42 -07004819 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004820
4821 char value[PROPERTY_VALUE_MAX];
4822 int trial;
4823 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4824 trial = atoi(value);
4825 if (period_size_is_plausible_for_low_latency(trial)) {
4826 pcm_config_low_latency.period_size = trial;
4827 pcm_config_low_latency.start_threshold = trial / 4;
4828 pcm_config_low_latency.avail_min = trial / 4;
4829 configured_low_latency_capture_period_size = trial;
4830 }
4831 }
4832 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4833 trial = atoi(value);
4834 if (period_size_is_plausible_for_low_latency(trial)) {
4835 configured_low_latency_capture_period_size = trial;
4836 }
4837 }
4838
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004839 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4840 af_period_multiplier = atoi(value);
4841 if (af_period_multiplier < 0)
4842 af_period_multiplier = 2;
4843 else if (af_period_multiplier > 4)
4844 af_period_multiplier = 4;
4845
4846 ALOGV("new period_multiplier = %d", af_period_multiplier);
4847 }
4848
vivek mehta446c3962015-09-14 10:57:35 -07004849 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004850 pthread_mutex_unlock(&adev_init_lock);
4851
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004852 if (adev->adm_init)
4853 adev->adm_data = adev->adm_init();
4854
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304855 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004856 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857 return 0;
4858}
4859
4860static struct hw_module_methods_t hal_module_methods = {
4861 .open = adev_open,
4862};
4863
4864struct audio_module HAL_MODULE_INFO_SYM = {
4865 .common = {
4866 .tag = HARDWARE_MODULE_TAG,
4867 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4868 .hal_api_version = HARDWARE_HAL_API_VERSION,
4869 .id = AUDIO_HARDWARE_MODULE_ID,
4870 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004871 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004872 .methods = &hal_module_methods,
4873 },
4874};