blob: af399a1e11919aad4ba067a60e9daa48da9e872e [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) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +0530895 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
896 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
897 (force_restart_session)) &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530898 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
899 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
900 __func__, use_case_table[usecase->id],
901 platform_get_snd_device_name(usecase->out_snd_device));
902 disable_audio_route(adev, usecase);
903 switch_device[usecase->id] = true;
904 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 }
906 }
907
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530908 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
909 num_uc_to_switch);
910
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700912 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700913
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530914 /* Make sure the previous devices to be disabled first and then enable the
915 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 list_for_each(node, &adev->usecase_list) {
917 usecase = node_to_item(node, struct audio_usecase, list);
918 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700919 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700920 }
921 }
922
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700923 list_for_each(node, &adev->usecase_list) {
924 usecase = node_to_item(node, struct audio_usecase, list);
925 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700926 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700927 }
928 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700929
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700930 /* Re-route all the usecases on the shared backend other than the
931 specified usecase to new snd devices */
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530934 /* Update the out_snd_device only before enabling the audio route */
935 if (switch_device[usecase->id]) {
936 usecase->out_snd_device = snd_device;
937 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530938 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530939 use_case_table[usecase->id],
940 platform_get_snd_device_name(usecase->out_snd_device));
Avinash Vaish71a8b972014-07-24 15:36:33 +0530941 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +0530942 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 }
944 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700945 }
946}
947
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530948static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 struct audio_usecase *uc_info,
950 snd_device_t snd_device)
951{
952 struct listnode *node;
953 struct audio_usecase *usecase;
954 bool switch_device[AUDIO_USECASE_MAX];
955 int i, num_uc_to_switch = 0;
956
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530957 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
958 snd_device);
959 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700960 /*
961 * This function is to make sure that all the active capture usecases
962 * are always routed to the same input sound device.
963 * For example, if audio-record and voice-call usecases are currently
964 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
965 * is received for voice call then we have to make sure that audio-record
966 * usecase is also switched to earpiece i.e. voice-dmic-ef,
967 * because of the limitation that two devices cannot be enabled
968 * at the same time if they share the same backend.
969 */
970 for (i = 0; i < AUDIO_USECASE_MAX; i++)
971 switch_device[i] = false;
972
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800975 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700976 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +0530977 (usecase->in_snd_device != snd_device || force_routing) &&
Narsinga Rao Chellaf99003c2015-07-08 19:38:38 -0700978 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +0530979 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +0800980 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -0700981 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700982 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
983 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700984 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700985 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700986 switch_device[usecase->id] = true;
987 num_uc_to_switch++;
988 }
989 }
990
991 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700992 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +0530994 /* Make sure the previous devices to be disabled first and then enable the
995 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700996 list_for_each(node, &adev->usecase_list) {
997 usecase = node_to_item(node, struct audio_usecase, list);
998 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700999 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001000 }
1001 }
1002
1003 list_for_each(node, &adev->usecase_list) {
1004 usecase = node_to_item(node, struct audio_usecase, list);
1005 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001006 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001007 }
1008 }
1009
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001010 /* Re-route all the usecases on the shared backend other than the
1011 specified usecase to new snd devices */
1012 list_for_each(node, &adev->usecase_list) {
1013 usecase = node_to_item(node, struct audio_usecase, list);
1014 /* Update the in_snd_device only before enabling the audio route */
1015 if (switch_device[usecase->id] ) {
1016 usecase->in_snd_device = snd_device;
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -08001017 if (usecase->type != VOICE_CALL)
Avinash Vaish71a8b972014-07-24 15:36:33 +05301018 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001019 }
1020 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001021 }
1022}
1023
Mingming Yin3a941d42016-02-17 18:08:05 -08001024static void reset_hdmi_sink_caps(struct stream_out *out) {
1025 int i = 0;
1026
1027 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1028 out->supported_channel_masks[i] = 0;
1029 }
1030 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1031 out->supported_formats[i] = 0;
1032 }
1033 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1034 out->supported_sample_rates[i] = 0;
1035 }
1036}
1037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001039static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040{
Mingming Yin3a941d42016-02-17 18:08:05 -08001041 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001042 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043
Mingming Yin3a941d42016-02-17 18:08:05 -08001044 reset_hdmi_sink_caps(out);
1045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001048 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001049 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001050 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1051 case 6:
1052 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1053 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1054 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1055 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1056 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1057 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 break;
1059 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001060 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001061 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062 break;
1063 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001064
1065 // check channel format caps
1066 i = 0;
1067 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1068 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1069 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1070 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1071 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1072 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1073 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1074 }
1075
1076 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1077 ALOGV(":%s HDMI supports DTS format", __func__);
1078 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1079 }
1080
1081 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1082 ALOGV(":%s HDMI supports DTS HD format", __func__);
1083 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1084 }
1085
1086
1087 // check sample rate caps
1088 i = 0;
1089 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1090 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1091 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1092 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1093 }
1094 }
1095
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001096 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097}
1098
Alexy Josephb1379942016-01-29 15:49:38 -08001099audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001100 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001101{
1102 struct audio_usecase *usecase;
1103 struct listnode *node;
1104
1105 list_for_each(node, &adev->usecase_list) {
1106 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001107 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001108 ALOGV("%s: usecase id %d", __func__, usecase->id);
1109 return usecase->id;
1110 }
1111 }
1112 return USECASE_INVALID;
1113}
1114
Alexy Josephb1379942016-01-29 15:49:38 -08001115struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001116 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117{
1118 struct audio_usecase *usecase;
1119 struct listnode *node;
1120
1121 list_for_each(node, &adev->usecase_list) {
1122 usecase = node_to_item(node, struct audio_usecase, list);
1123 if (usecase->id == uc_id)
1124 return usecase;
1125 }
1126 return NULL;
1127}
1128
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301129/*
1130 * is a true native playback active
1131 */
1132bool audio_is_true_native_stream_active(struct audio_device *adev)
1133{
1134 bool active = false;
1135 int i = 0;
1136 struct listnode *node;
1137
1138 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1139 ALOGV("%s:napb: not in true mode or non hdphones device",
1140 __func__);
1141 active = false;
1142 goto exit;
1143 }
1144
1145 list_for_each(node, &adev->usecase_list) {
1146 struct audio_usecase *uc;
1147 uc = node_to_item(node, struct audio_usecase, list);
1148 struct stream_out *curr_out =
1149 (struct stream_out*) uc->stream.out;
1150
1151 if (curr_out && PCM_PLAYBACK == uc->type) {
1152 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1153 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1154 uc->id, curr_out->sample_rate,
1155 curr_out->bit_width,
1156 platform_get_snd_device_name(uc->out_snd_device));
1157
1158 if (is_offload_usecase(uc->id) &&
1159 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1160 active = true;
1161 ALOGD("%s:napb:native stream detected", __func__);
1162 }
1163 }
1164 }
1165exit:
1166 return active;
1167}
1168
1169
1170static bool force_device_switch(struct audio_usecase *usecase)
1171{
1172 bool ret = false;
1173 bool is_it_true_mode = false;
1174
1175 if (is_offload_usecase(usecase->id) &&
1176 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001177 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1178 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1179 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301180 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1181 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1182 (!is_it_true_mode && adev->native_playback_enabled)){
1183 ret = true;
1184 ALOGD("napb: time to toggle native mode");
1185 }
1186 }
1187
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301188 // Force all a2dp output devices to reconfigure for proper AFE encode format
1189 if((usecase->stream.out) &&
1190 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
1191 audio_extn_a2dp_is_force_device_switch()) {
1192 ALOGD("Force a2dp device switch to update new encoder config");
1193 ret = true;
1194 }
1195
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301196 return ret;
1197}
1198
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001199int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001200{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001201 snd_device_t out_snd_device = SND_DEVICE_NONE;
1202 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203 struct audio_usecase *usecase = NULL;
1204 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001205 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001206 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001207 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001208 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001209
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301210 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1211
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 usecase = get_usecase_from_list(adev, uc_id);
1213 if (usecase == NULL) {
1214 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1215 return -EINVAL;
1216 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001217
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001218 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001219 (usecase->type == VOIP_CALL) ||
1220 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001221 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001222 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001223 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001224 usecase->devices = usecase->stream.out->devices;
1225 } else {
1226 /*
1227 * If the voice call is active, use the sound devices of voice call usecase
1228 * so that it would not result any device switch. All the usecases will
1229 * be switched to new device when select_devices() is called for voice call
1230 * usecase. This is to avoid switching devices for voice call when
1231 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001232 * choose voice call device only if the use case device is
1233 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001235 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001236 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001237 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001238 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1239 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301240 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1241 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001242 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243 in_snd_device = vc_usecase->in_snd_device;
1244 out_snd_device = vc_usecase->out_snd_device;
1245 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001246 } else if (voice_extn_compress_voip_is_active(adev)) {
1247 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001248 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001249 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1250 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001251 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001252 in_snd_device = voip_usecase->in_snd_device;
1253 out_snd_device = voip_usecase->out_snd_device;
1254 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001255 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001256 hfp_ucid = audio_extn_hfp_get_usecase();
1257 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001258 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001259 in_snd_device = hfp_usecase->in_snd_device;
1260 out_snd_device = hfp_usecase->out_snd_device;
1261 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262 }
1263 if (usecase->type == PCM_PLAYBACK) {
1264 usecase->devices = usecase->stream.out->devices;
1265 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001266 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001267 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001268 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001269 if (usecase->stream.out == adev->primary_output &&
1270 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001271 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001272 select_devices(adev, adev->active_input->usecase);
1273 }
1274 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001275 } else if (usecase->type == PCM_CAPTURE) {
1276 usecase->devices = usecase->stream.in->device;
1277 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001278 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001279 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001280 if (adev->active_input &&
1281 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301282 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1283 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1284 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001285 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001286 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001287 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1288 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001289 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001290 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001291 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 }
1293 }
1294
1295 if (out_snd_device == usecase->out_snd_device &&
1296 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301297
1298 if (!force_device_switch(usecase))
1299 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300 }
1301
sangwoobc677242013-08-08 16:53:43 +09001302 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001303 out_snd_device, platform_get_snd_device_name(out_snd_device),
1304 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001306 /*
1307 * Limitation: While in call, to do a device switch we need to disable
1308 * and enable both RX and TX devices though one of them is same as current
1309 * device.
1310 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001311 if ((usecase->type == VOICE_CALL) &&
1312 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1313 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001314 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001315 }
1316
1317 if (((usecase->type == VOICE_CALL) ||
1318 (usecase->type == VOIP_CALL)) &&
1319 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1320 /* Disable sidetone only if voice/voip call already exists */
1321 if (voice_is_call_state_active(adev) ||
1322 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001323 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001324 }
1325
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001326 /* Disable current sound devices */
1327 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001328 disable_audio_route(adev, usecase);
1329 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330 }
1331
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001332 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001333 disable_audio_route(adev, usecase);
1334 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335 }
1336
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001337 /* Applicable only on the targets that has external modem.
1338 * New device information should be sent to modem before enabling
1339 * the devices to reduce in-call device switch time.
1340 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001341 if ((usecase->type == VOICE_CALL) &&
1342 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1343 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001344 status = platform_switch_voice_call_enable_device_config(adev->platform,
1345 out_snd_device,
1346 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001347 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001348
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001349 /* Enable new sound devices */
1350 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001351 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001352 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353 }
1354
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001355 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301356 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001357 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001358 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359
Avinash Vaish71a8b972014-07-24 15:36:33 +05301360 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001361 status = platform_switch_voice_call_device_post(adev->platform,
1362 out_snd_device,
1363 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301364 enable_audio_route_for_voice_usecases(adev, usecase);
1365 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001366
sangwoo170731f2013-06-08 15:36:36 +09001367 usecase->in_snd_device = in_snd_device;
1368 usecase->out_snd_device = out_snd_device;
1369
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301370 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001371 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301372 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001373 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301374 usecase->stream.out->flags,
1375 usecase->stream.out->format,
1376 usecase->stream.out->sample_rate,
1377 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301378 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301379 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001380 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301381 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001382
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001383 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001384
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001385 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
1386 /* Enable sidetone only if other voice/voip call already exists */
1387 if (voice_is_call_state_active(adev) ||
1388 voice_extn_compress_voip_is_started(adev))
1389 voice_set_sidetone(adev, out_snd_device, true);
1390 }
1391
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001392 /* Applicable only on the targets that has external modem.
1393 * Enable device command should be sent to modem only after
1394 * enabling voice call mixer controls
1395 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001396 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001397 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1398 out_snd_device,
1399 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301400 ALOGD("%s: done",__func__);
1401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402 return status;
1403}
1404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405static int stop_input_stream(struct stream_in *in)
1406{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301407 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001408 struct audio_usecase *uc_info;
1409 struct audio_device *adev = in->dev;
1410
Eric Laurentc8400632013-02-14 19:04:54 -08001411 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412
Eric Laurent994a6932013-07-17 11:51:42 -07001413 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001414 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415 uc_info = get_usecase_from_list(adev, in->usecase);
1416 if (uc_info == NULL) {
1417 ALOGE("%s: Could not find the usecase (%d) in the list",
1418 __func__, in->usecase);
1419 return -EINVAL;
1420 }
1421
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001422 /* Close in-call recording streams */
1423 voice_check_and_stop_incall_rec_usecase(adev, in);
1424
Eric Laurent150dbfe2013-02-27 14:31:02 -08001425 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001426 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427
1428 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001429 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001431 list_remove(&uc_info->list);
1432 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001433
Eric Laurent994a6932013-07-17 11:51:42 -07001434 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001435 return ret;
1436}
1437
1438int start_input_stream(struct stream_in *in)
1439{
1440 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001441 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 struct audio_usecase *uc_info;
1443 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301444 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445
Mingming Yin2664a5b2015-09-03 10:53:11 -07001446 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1447 if (get_usecase_from_list(adev, usecase) == NULL)
1448 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301449 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1450 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001451
Naresh Tanniru80659832014-06-04 18:17:56 +05301452
1453 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301454 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301455 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301456 goto error_config;
1457 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301458
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001459 /* Check if source matches incall recording usecase criteria */
1460 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1461 if (ret)
1462 goto error_config;
1463 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001464 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1465
1466 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1467 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1468 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001469 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001470 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001471
Eric Laurentb23d5282013-05-14 15:27:20 -07001472 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473 if (in->pcm_device_id < 0) {
1474 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1475 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001476 ret = -EINVAL;
1477 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001479
1480 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001482
1483 if (!uc_info) {
1484 ret = -ENOMEM;
1485 goto error_config;
1486 }
1487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488 uc_info->id = in->usecase;
1489 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001490 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491 uc_info->devices = in->device;
1492 uc_info->in_snd_device = SND_DEVICE_NONE;
1493 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001495 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301496 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1497 adev->perf_lock_opts,
1498 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301501 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1502 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001503
1504 unsigned int flags = PCM_IN;
1505 unsigned int pcm_open_retry_count = 0;
1506
1507 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1508 flags |= PCM_MMAP | PCM_NOIRQ;
1509 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001510 } else if (in->realtime) {
1511 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001512 }
1513
1514 while (1) {
1515 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1516 flags, &in->config);
1517 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1518 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1519 if (in->pcm != NULL) {
1520 pcm_close(in->pcm);
1521 in->pcm = NULL;
1522 }
1523 if (pcm_open_retry_count-- == 0) {
1524 ret = -EIO;
1525 goto error_open;
1526 }
1527 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1528 continue;
1529 }
1530 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001532
1533 ALOGV("%s: pcm_prepare", __func__);
1534 ret = pcm_prepare(in->pcm);
1535 if (ret < 0) {
1536 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1537 pcm_close(in->pcm);
1538 in->pcm = NULL;
1539 goto error_open;
1540 }
1541
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001542 register_in_stream(in);
1543 if (in->realtime) {
1544 ret = pcm_start(in->pcm);
1545 if (ret < 0)
1546 goto error_open;
1547 }
1548
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301549 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001550 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001551
Eric Laurentc8400632013-02-14 19:04:54 -08001552 return ret;
1553
1554error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301555 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001557error_config:
1558 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301559 /*
1560 * sleep 50ms to allow sufficient time for kernel
1561 * drivers to recover incases like SSR.
1562 */
1563 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001565
1566 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567}
1568
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001569void lock_input_stream(struct stream_in *in)
1570{
1571 pthread_mutex_lock(&in->pre_lock);
1572 pthread_mutex_lock(&in->lock);
1573 pthread_mutex_unlock(&in->pre_lock);
1574}
1575
1576void lock_output_stream(struct stream_out *out)
1577{
1578 pthread_mutex_lock(&out->pre_lock);
1579 pthread_mutex_lock(&out->lock);
1580 pthread_mutex_unlock(&out->pre_lock);
1581}
1582
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001583/* must be called with out->lock locked */
1584static int send_offload_cmd_l(struct stream_out* out, int command)
1585{
1586 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1587
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001588 if (!cmd) {
1589 ALOGE("failed to allocate mem for command 0x%x", command);
1590 return -ENOMEM;
1591 }
1592
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001593 ALOGVV("%s %d", __func__, command);
1594
1595 cmd->cmd = command;
1596 list_add_tail(&out->offload_cmd_list, &cmd->node);
1597 pthread_cond_signal(&out->offload_cond);
1598 return 0;
1599}
1600
1601/* must be called iwth out->lock locked */
1602static void stop_compressed_output_l(struct stream_out *out)
1603{
1604 out->offload_state = OFFLOAD_STATE_IDLE;
1605 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001606 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 if (out->compr != NULL) {
1608 compress_stop(out->compr);
1609 while (out->offload_thread_blocked) {
1610 pthread_cond_wait(&out->cond, &out->lock);
1611 }
1612 }
1613}
1614
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001615bool is_offload_usecase(audio_usecase_t uc_id)
1616{
1617 unsigned int i;
1618 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1619 if (uc_id == offload_usecases[i])
1620 return true;
1621 }
1622 return false;
1623}
1624
vivek mehta446c3962015-09-14 10:57:35 -07001625static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001626{
vivek mehta446c3962015-09-14 10:57:35 -07001627 audio_usecase_t ret_uc = USECASE_INVALID;
1628 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001629 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001630 if (!adev->multi_offload_enable) {
1631 if (is_direct_pcm)
1632 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1633 else
1634 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001635
vivek mehta446c3962015-09-14 10:57:35 -07001636 pthread_mutex_lock(&adev->lock);
1637 if (get_usecase_from_list(adev, ret_uc) != NULL)
1638 ret_uc = USECASE_INVALID;
1639 pthread_mutex_unlock(&adev->lock);
1640
1641 return ret_uc;
1642 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001643
1644 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001645 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1646 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1647 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1648 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001649 break;
1650 }
1651 }
vivek mehta446c3962015-09-14 10:57:35 -07001652
1653 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1654 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001655}
1656
1657static void free_offload_usecase(struct audio_device *adev,
1658 audio_usecase_t uc_id)
1659{
vivek mehta446c3962015-09-14 10:57:35 -07001660 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001661 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001662
1663 if (!adev->multi_offload_enable)
1664 return;
1665
1666 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1667 if (offload_usecases[offload_uc_index] == uc_id) {
1668 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001669 break;
1670 }
1671 }
1672 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1673}
1674
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001675static void *offload_thread_loop(void *context)
1676{
1677 struct stream_out *out = (struct stream_out *) context;
1678 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001679 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1682 set_sched_policy(0, SP_FOREGROUND);
1683 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1684
1685 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001686 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001687 for (;;) {
1688 struct offload_cmd *cmd = NULL;
1689 stream_callback_event_t event;
1690 bool send_callback = false;
1691
1692 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1693 __func__, list_empty(&out->offload_cmd_list),
1694 out->offload_state);
1695 if (list_empty(&out->offload_cmd_list)) {
1696 ALOGV("%s SLEEPING", __func__);
1697 pthread_cond_wait(&out->offload_cond, &out->lock);
1698 ALOGV("%s RUNNING", __func__);
1699 continue;
1700 }
1701
1702 item = list_head(&out->offload_cmd_list);
1703 cmd = node_to_item(item, struct offload_cmd, node);
1704 list_remove(item);
1705
1706 ALOGVV("%s STATE %d CMD %d out->compr %p",
1707 __func__, out->offload_state, cmd->cmd, out->compr);
1708
1709 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1710 free(cmd);
1711 break;
1712 }
1713
1714 if (out->compr == NULL) {
1715 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001716 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717 pthread_cond_signal(&out->cond);
1718 continue;
1719 }
1720 out->offload_thread_blocked = true;
1721 pthread_mutex_unlock(&out->lock);
1722 send_callback = false;
1723 switch(cmd->cmd) {
1724 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001725 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001726 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001727 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001728 send_callback = true;
1729 event = STREAM_CBK_EVENT_WRITE_READY;
1730 break;
1731 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001732 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301733 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001734 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301735 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001736 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301737 if (ret < 0)
1738 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301739 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301740 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001741 compress_drain(out->compr);
1742 else
1743 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301744 if (ret != -ENETRESET) {
1745 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301746 pthread_mutex_lock(&out->lock);
1747 out->send_new_metadata = 1;
1748 out->send_next_track_params = true;
1749 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301750 event = STREAM_CBK_EVENT_DRAIN_READY;
1751 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1752 } else
1753 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754 break;
1755 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001756 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001758 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001759 send_callback = true;
1760 event = STREAM_CBK_EVENT_DRAIN_READY;
1761 break;
1762 default:
1763 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1764 break;
1765 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001766 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 out->offload_thread_blocked = false;
1768 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001769 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001770 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001772 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001773 free(cmd);
1774 }
1775
1776 pthread_cond_signal(&out->cond);
1777 while (!list_empty(&out->offload_cmd_list)) {
1778 item = list_head(&out->offload_cmd_list);
1779 list_remove(item);
1780 free(node_to_item(item, struct offload_cmd, node));
1781 }
1782 pthread_mutex_unlock(&out->lock);
1783
1784 return NULL;
1785}
1786
1787static int create_offload_callback_thread(struct stream_out *out)
1788{
1789 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1790 list_init(&out->offload_cmd_list);
1791 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1792 offload_thread_loop, out);
1793 return 0;
1794}
1795
1796static int destroy_offload_callback_thread(struct stream_out *out)
1797{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001798 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 stop_compressed_output_l(out);
1800 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1801
1802 pthread_mutex_unlock(&out->lock);
1803 pthread_join(out->offload_thread, (void **) NULL);
1804 pthread_cond_destroy(&out->offload_cond);
1805
1806 return 0;
1807}
1808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809static int stop_output_stream(struct stream_out *out)
1810{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301811 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 struct audio_usecase *uc_info;
1813 struct audio_device *adev = out->dev;
1814
Eric Laurent994a6932013-07-17 11:51:42 -07001815 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817 uc_info = get_usecase_from_list(adev, out->usecase);
1818 if (uc_info == NULL) {
1819 ALOGE("%s: Could not find the usecase (%d) in the list",
1820 __func__, out->usecase);
1821 return -EINVAL;
1822 }
1823
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001824 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301825 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001826 if (adev->visualizer_stop_output != NULL)
1827 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001828
1829 audio_extn_dts_remove_state_notifier_node(out->usecase);
1830
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001831 if (adev->offload_effects_stop_output != NULL)
1832 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1833 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001834
Eric Laurent150dbfe2013-02-27 14:31:02 -08001835 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001836 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001837
1838 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001839 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001841 list_remove(&uc_info->list);
1842 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001844 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301845 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001846 ALOGV("Disable passthrough , reset mixer to pcm");
1847 /* NO_PASSTHROUGH */
1848 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001849 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001850 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1851 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001852
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301853 /* Must be called after removing the usecase from list */
1854 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301855 audio_extn_keep_alive_start();
1856
Eric Laurent994a6932013-07-17 11:51:42 -07001857 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 return ret;
1859}
1860
1861int start_output_stream(struct stream_out *out)
1862{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 struct audio_usecase *uc_info;
1865 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301866 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001868 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1869 ret = -EINVAL;
1870 goto error_config;
1871 }
1872
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301873 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1874 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1875 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301876
Naresh Tanniru80659832014-06-04 18:17:56 +05301877 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301878 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301879 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301880 goto error_config;
1881 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301882
Eric Laurentb23d5282013-05-14 15:27:20 -07001883 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 if (out->pcm_device_id < 0) {
1885 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1886 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001887 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001888 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889 }
1890
1891 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001892
1893 if (!uc_info) {
1894 ret = -ENOMEM;
1895 goto error_config;
1896 }
1897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898 uc_info->id = out->usecase;
1899 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001900 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 uc_info->devices = out->devices;
1902 uc_info->in_snd_device = SND_DEVICE_NONE;
1903 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001904 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001905
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301906 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1907 adev->perf_lock_opts,
1908 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301909
1910 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1911 audio_extn_keep_alive_stop();
1912 if (audio_extn_passthru_is_enabled() &&
1913 audio_extn_passthru_is_passthrough_stream(out)) {
1914 audio_extn_passthru_on_start(out);
1915 audio_extn_passthru_update_stream_configuration(adev, out);
1916 }
1917 }
1918
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 select_devices(adev, out->usecase);
1920
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001921 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1922 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001923 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001924 unsigned int flags = PCM_OUT;
1925 unsigned int pcm_open_retry_count = 0;
1926 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1927 flags |= PCM_MMAP | PCM_NOIRQ;
1928 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001929 } else if (out->realtime) {
1930 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001931 } else
1932 flags |= PCM_MONOTONIC;
1933
1934 while (1) {
1935 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1936 flags, &out->config);
1937 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1938 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1939 if (out->pcm != NULL) {
1940 pcm_close(out->pcm);
1941 out->pcm = NULL;
1942 }
1943 if (pcm_open_retry_count-- == 0) {
1944 ret = -EIO;
1945 goto error_open;
1946 }
1947 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1948 continue;
1949 }
1950 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001952
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001953 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1954 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001955
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001956 ALOGV("%s: pcm_prepare", __func__);
1957 if (pcm_is_ready(out->pcm)) {
1958 ret = pcm_prepare(out->pcm);
1959 if (ret < 0) {
1960 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1961 pcm_close(out->pcm);
1962 out->pcm = NULL;
1963 goto error_open;
1964 }
1965 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001967 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1968 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001970 out->compr = compress_open(adev->snd_card,
1971 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972 COMPRESS_IN, &out->compr_config);
1973 if (out->compr && !is_compress_ready(out->compr)) {
1974 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1975 compress_close(out->compr);
1976 out->compr = NULL;
1977 ret = -EIO;
1978 goto error_open;
1979 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301980 /* compress_open sends params of the track, so reset the flag here */
1981 out->is_compr_metadata_avail = false;
1982
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001983 if (out->offload_callback)
1984 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001985
Fred Oh3f43e742015-03-04 18:42:34 -08001986 /* Since small bufs uses blocking writes, a write will be blocked
1987 for the default max poll time (20s) in the event of an SSR.
1988 Reduce the poll time to observe and deal with SSR faster.
1989 */
Ashish Jain5106d362016-05-11 19:23:33 +05301990 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001991 compress_set_max_poll_wait(out->compr, 1000);
1992 }
1993
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001994 audio_extn_dts_create_state_notifier_node(out->usecase);
1995 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1996 popcount(out->channel_mask),
1997 out->playback_started);
1998
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001999#ifdef DS1_DOLBY_DDP_ENABLED
2000 if (audio_extn_is_dolby_format(out->format))
2001 audio_extn_dolby_send_ddp_endp_params(adev);
2002#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302003 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002004 if (adev->visualizer_start_output != NULL)
2005 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2006 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302007 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002008 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002011
2012 if (ret == 0) {
2013 register_out_stream(out);
2014 if (out->realtime) {
2015 ret = pcm_start(out->pcm);
2016 if (ret < 0)
2017 goto error_open;
2018 }
2019 }
2020
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302021 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002022 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002023
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002024 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002025error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302026 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002028error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302029 /*
2030 * sleep 50ms to allow sufficient time for kernel
2031 * drivers to recover incases like SSR.
2032 */
2033 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002034 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035}
2036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037static int check_input_parameters(uint32_t sample_rate,
2038 audio_format_t format,
2039 int channel_count)
2040{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002041 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302043 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2044 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2045 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002046 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302047 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002048
2049 switch (channel_count) {
2050 case 1:
2051 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302052 case 3:
2053 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002054 case 6:
2055 break;
2056 default:
2057 ret = -EINVAL;
2058 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059
2060 switch (sample_rate) {
2061 case 8000:
2062 case 11025:
2063 case 12000:
2064 case 16000:
2065 case 22050:
2066 case 24000:
2067 case 32000:
2068 case 44100:
2069 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302070 case 96000:
2071 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 break;
2073 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002074 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 }
2076
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002077 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078}
2079
2080static size_t get_input_buffer_size(uint32_t sample_rate,
2081 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002082 int channel_count,
2083 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084{
2085 size_t size = 0;
2086
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002087 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2088 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002090 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002091 if (is_low_latency)
2092 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302093
2094 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002096 /* make sure the size is multiple of 32 bytes
2097 * At 48 kHz mono 16-bit PCM:
2098 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2099 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2100 */
2101 size += 0x1f;
2102 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002103
2104 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105}
2106
Ashish Jain5106d362016-05-11 19:23:33 +05302107static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2108{
2109 uint64_t actual_frames_rendered = 0;
2110 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2111
2112 /* This adjustment accounts for buffering after app processor.
2113 * It is based on estimated DSP latency per use case, rather than exact.
2114 */
2115 int64_t platform_latency = platform_render_latency(out->usecase) *
2116 out->sample_rate / 1000000LL;
2117
2118 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2119 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2120 * hence only estimate.
2121 */
2122 int64_t signed_frames = out->written - kernel_buffer_size;
2123
2124 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2125
2126 if (signed_frames > 0)
2127 actual_frames_rendered = signed_frames;
2128
2129 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2130 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2131 (long long int)out->written, (int)kernel_buffer_size,
2132 audio_bytes_per_sample(out->compr_config.codec->format),
2133 popcount(out->channel_mask));
2134
2135 return actual_frames_rendered;
2136}
2137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2139{
2140 struct stream_out *out = (struct stream_out *)stream;
2141
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143}
2144
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002145static int out_set_sample_rate(struct audio_stream *stream __unused,
2146 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147{
2148 return -ENOSYS;
2149}
2150
2151static size_t out_get_buffer_size(const struct audio_stream *stream)
2152{
2153 struct stream_out *out = (struct stream_out *)stream;
2154
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002155 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002157 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2158 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302159 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302160 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002161
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002162 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002163 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164}
2165
2166static uint32_t out_get_channels(const struct audio_stream *stream)
2167{
2168 struct stream_out *out = (struct stream_out *)stream;
2169
2170 return out->channel_mask;
2171}
2172
2173static audio_format_t out_get_format(const struct audio_stream *stream)
2174{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 struct stream_out *out = (struct stream_out *)stream;
2176
2177 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178}
2179
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002180static int out_set_format(struct audio_stream *stream __unused,
2181 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182{
2183 return -ENOSYS;
2184}
2185
2186static int out_standby(struct audio_stream *stream)
2187{
2188 struct stream_out *out = (struct stream_out *)stream;
2189 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002190
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302191 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2192 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002193
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002194 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002196 if (adev->adm_deregister_stream)
2197 adev->adm_deregister_stream(adev->adm_data, out->handle);
2198
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002199 if (is_offload_usecase(out->usecase))
2200 stop_compressed_output_l(out);
2201
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002202 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002204 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2205 voice_extn_compress_voip_close_output_stream(stream);
2206 pthread_mutex_unlock(&adev->lock);
2207 pthread_mutex_unlock(&out->lock);
2208 ALOGD("VOIP output entered standby");
2209 return 0;
2210 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002211 if (out->pcm) {
2212 pcm_close(out->pcm);
2213 out->pcm = NULL;
2214 }
2215 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002216 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302217 out->send_next_track_params = false;
2218 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002219 out->gapless_mdata.encoder_delay = 0;
2220 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 if (out->compr != NULL) {
2222 compress_close(out->compr);
2223 out->compr = NULL;
2224 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002227 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 }
2229 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302230 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 return 0;
2232}
2233
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002234static int out_dump(const struct audio_stream *stream __unused,
2235 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236{
2237 return 0;
2238}
2239
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002240static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2241{
2242 int ret = 0;
2243 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002244
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002246 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002247 return -EINVAL;
2248 }
2249
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302250 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002251
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002252 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2253 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302254 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002255 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002256 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2257 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302258 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002259 }
2260
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002261 ALOGV("%s new encoder delay %u and padding %u", __func__,
2262 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2263
2264 return 0;
2265}
2266
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002267static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2268{
2269 return out == adev->primary_output || out == adev->voice_tx_output;
2270}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2273{
2274 struct stream_out *out = (struct stream_out *)stream;
2275 struct audio_device *adev = out->dev;
2276 struct str_parms *parms;
2277 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002278 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279
sangwoobc677242013-08-08 16:53:43 +09002280 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002281 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302283 if (!parms)
2284 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002285 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2286 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002288 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002289 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002291 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002292 * When HDMI cable is unplugged the music playback is paused and
2293 * the policy manager sends routing=0. But the audioflinger continues
2294 * to write data until standby time (3sec). As the HDMI core is
2295 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002296 * Avoid this by routing audio to speaker until standby.
2297 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002298 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2299 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302300 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002301 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2302 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002303 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302304 /*
2305 * When A2DP is disconnected the
2306 * music playback is paused and the policy manager sends routing=0
2307 * But the audioflingercontinues to write data until standby time
2308 * (3sec). As BT is turned off, the write gets blocked.
2309 * Avoid this by routing audio to speaker until standby.
2310 */
2311 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2312 (val == AUDIO_DEVICE_NONE)) {
2313 val = AUDIO_DEVICE_OUT_SPEAKER;
2314 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002315
2316 /*
2317 * select_devices() call below switches all the usecases on the same
2318 * backend to the new device. Refer to check_usecases_codec_backend() in
2319 * the select_devices(). But how do we undo this?
2320 *
2321 * For example, music playback is active on headset (deep-buffer usecase)
2322 * and if we go to ringtones and select a ringtone, low-latency usecase
2323 * will be started on headset+speaker. As we can't enable headset+speaker
2324 * and headset devices at the same time, select_devices() switches the music
2325 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2326 * So when the ringtone playback is completed, how do we undo the same?
2327 *
2328 * We are relying on the out_set_parameters() call on deep-buffer output,
2329 * once the ringtone playback is ended.
2330 * NOTE: We should not check if the current devices are same as new devices.
2331 * Because select_devices() must be called to switch back the music
2332 * playback to headset.
2333 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002334 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002335 audio_devices_t new_dev = val;
2336 bool same_dev = out->devices == new_dev;
2337 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002338
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002339 if (output_drives_call(adev, out)) {
2340 if(!voice_is_in_call(adev)) {
2341 if (adev->mode == AUDIO_MODE_IN_CALL) {
2342 adev->current_call_output = out;
2343 ret = voice_start_call(adev);
2344 }
2345 } else {
2346 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002347 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002348 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002349 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002350
2351 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002352 if (!same_dev) {
2353 ALOGV("update routing change");
2354 out->routing_change = true;
Sudheer Papothi80266982016-08-16 02:36:18 +05302355 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2356 adev->perf_lock_opts,
2357 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002358 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002359 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302360 if (!same_dev)
2361 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002362 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002363 }
2364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002366 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002368
2369 if (out == adev->primary_output) {
2370 pthread_mutex_lock(&adev->lock);
2371 audio_extn_set_parameters(adev, parms);
2372 pthread_mutex_unlock(&adev->lock);
2373 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002374 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002375 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002376 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002377
2378 audio_extn_dts_create_state_notifier_node(out->usecase);
2379 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2380 popcount(out->channel_mask),
2381 out->playback_started);
2382
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002383 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002384 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302387error:
Eric Laurent994a6932013-07-17 11:51:42 -07002388 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 return ret;
2390}
2391
2392static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2393{
2394 struct stream_out *out = (struct stream_out *)stream;
2395 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002396 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 char value[256];
2398 struct str_parms *reply = str_parms_create();
2399 size_t i, j;
2400 int ret;
2401 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002402
2403 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002404 if (reply) {
2405 str_parms_destroy(reply);
2406 }
2407 if (query) {
2408 str_parms_destroy(query);
2409 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002410 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2411 return NULL;
2412 }
2413
Eric Laurent994a6932013-07-17 11:51:42 -07002414 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2416 if (ret >= 0) {
2417 value[0] = '\0';
2418 i = 0;
2419 while (out->supported_channel_masks[i] != 0) {
2420 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2421 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2422 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002423 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002425 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426 first = false;
2427 break;
2428 }
2429 }
2430 i++;
2431 }
2432 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2433 str = str_parms_to_str(reply);
2434 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002435 voice_extn_out_get_parameters(out, query, reply);
2436 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002437 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002438 free(str);
2439 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002442
Alexy Joseph62142aa2015-11-16 15:10:34 -08002443
2444 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2445 if (ret >= 0) {
2446 value[0] = '\0';
2447 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2448 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302449 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002450 } else {
2451 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302452 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002453 }
2454 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002455 if (str)
2456 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002457 str = str_parms_to_str(reply);
2458 }
2459
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002460 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2461 if (ret >= 0) {
2462 value[0] = '\0';
2463 i = 0;
2464 first = true;
2465 while (out->supported_formats[i] != 0) {
2466 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2467 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2468 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002469 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002470 }
2471 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2472 first = false;
2473 break;
2474 }
2475 }
2476 i++;
2477 }
2478 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002479 if (str)
2480 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002481 str = str_parms_to_str(reply);
2482 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002483
2484 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2485 if (ret >= 0) {
2486 value[0] = '\0';
2487 i = 0;
2488 first = true;
2489 while (out->supported_sample_rates[i] != 0) {
2490 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2491 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2492 if (!first) {
2493 strlcat(value, "|", sizeof(value));
2494 }
2495 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2496 first = false;
2497 break;
2498 }
2499 }
2500 i++;
2501 }
2502 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2503 if (str)
2504 free(str);
2505 str = str_parms_to_str(reply);
2506 }
2507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 str_parms_destroy(query);
2509 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002510 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 return str;
2512}
2513
2514static uint32_t out_get_latency(const struct audio_stream_out *stream)
2515{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002516 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002518 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519
Alexy Josephaa54c872014-12-03 02:46:47 -08002520 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002521 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002522 } else if (out->realtime) {
2523 // since the buffer won't be filled up faster than realtime,
2524 // return a smaller number
2525 if (out->config.rate)
2526 period_ms = (out->af_period_multiplier * out->config.period_size *
2527 1000) / (out->config.rate);
2528 else
2529 period_ms = 0;
2530 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002531 } else {
2532 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002534 }
2535
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302536 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002537 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538}
2539
2540static int out_set_volume(struct audio_stream_out *stream, float left,
2541 float right)
2542{
Eric Laurenta9024de2013-04-04 09:19:12 -07002543 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002544 int volume[2];
2545
Eric Laurenta9024de2013-04-04 09:19:12 -07002546 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2547 /* only take left channel into account: the API is for stereo anyway */
2548 out->muted = (left == 0.0f);
2549 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002550 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302551 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002552 /*
2553 * Set mute or umute on HDMI passthrough stream.
2554 * Only take left channel into account.
2555 * Mute is 0 and unmute 1
2556 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302557 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002558 } else {
2559 char mixer_ctl_name[128];
2560 struct audio_device *adev = out->dev;
2561 struct mixer_ctl *ctl;
2562 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002563 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002564
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002565 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2566 "Compress Playback %d Volume", pcm_device_id);
2567 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2568 if (!ctl) {
2569 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2570 __func__, mixer_ctl_name);
2571 return -EINVAL;
2572 }
2573 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2574 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2575 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2576 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002577 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002578 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 return -ENOSYS;
2581}
2582
2583static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2584 size_t bytes)
2585{
2586 struct stream_out *out = (struct stream_out *)stream;
2587 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302588 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002589 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002591 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302592
Naresh Tanniru80659832014-06-04 18:17:56 +05302593 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002594
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302595 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302596 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302597 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2598 pthread_mutex_unlock(&out->lock);
2599 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302600 } else {
2601 /* increase written size during SSR to avoid mismatch
2602 * with the written frames count in AF
2603 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302604 if (audio_bytes_per_sample(out->format) != 0)
2605 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302606 ALOGD(" %s: sound card is not active/SSR state", __func__);
2607 ret= -EIO;
2608 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302609 }
2610 }
2611
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302612 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302613 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2614 if (audio_bytes_per_sample(out->format) != 0)
2615 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2616 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302617 goto exit;
2618 }
2619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002621 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002622 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002623 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2624 ret = voice_extn_compress_voip_start_output_stream(out);
2625 else
2626 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002627 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002628 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002630 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 goto exit;
2632 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002633
2634 if (last_known_cal_step != -1) {
2635 ALOGD("%s: retry previous failed cal level set", __func__);
2636 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639
Ashish Jain81eb2a82015-05-13 10:52:34 +05302640 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002641 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302642 adev->is_channel_status_set = true;
2643 }
2644
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002645 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002646 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002647 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002648 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002649 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2650 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302651 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2652 ALOGD("copl(%p):send next track params in gapless", out);
2653 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2654 out->send_next_track_params = false;
2655 out->is_compr_metadata_avail = false;
2656 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002657 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302658 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302659 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002660
Ashish Jain83a6cc22016-06-28 14:34:17 +05302661 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302662 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302663 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302664 pthread_mutex_unlock(&out->lock);
2665 return -EINVAL;
2666 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302667 audio_format_t dst_format = out->hal_op_format;
2668 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302669
2670 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2671 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2672
Ashish Jain83a6cc22016-06-28 14:34:17 +05302673 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302674 dst_format,
2675 buffer,
2676 src_format,
2677 frames);
2678
Ashish Jain83a6cc22016-06-28 14:34:17 +05302679 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302680 bytes_to_write);
2681
2682 /*Convert written bytes in audio flinger format*/
2683 if (ret > 0)
2684 ret = ((ret * format_to_bitwidth_table[out->format]) /
2685 format_to_bitwidth_table[dst_format]);
2686 }
2687 } else
2688 ret = compress_write(out->compr, buffer, bytes);
2689
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302690 if (ret < 0)
2691 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302692 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002693 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302694 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002695 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302696 } else if (-ENETRESET == ret) {
2697 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2698 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2699 pthread_mutex_unlock(&out->lock);
2700 out_standby(&out->stream.common);
2701 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002702 }
Ashish Jain5106d362016-05-11 19:23:33 +05302703 if ( ret == (ssize_t)bytes && !out->non_blocking)
2704 out->written += bytes;
2705
Naresh Tanniru80659832014-06-04 18:17:56 +05302706 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002708 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002709 out->playback_started = 1;
2710 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002711
2712 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2713 popcount(out->channel_mask),
2714 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715 }
2716 pthread_mutex_unlock(&out->lock);
2717 return ret;
2718 } else {
2719 if (out->pcm) {
2720 if (out->muted)
2721 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002722
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302723 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002724
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002725 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002726
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002727 if (out->config.rate)
2728 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2729 out->config.rate;
2730
2731 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2732
2733 request_out_focus(out, ns);
2734
2735 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002736 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002737 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302738 out->convert_buffer != NULL) {
2739
2740 memcpy_by_audio_format(out->convert_buffer,
2741 out->hal_op_format,
2742 buffer,
2743 out->hal_ip_format,
2744 out->config.period_size * out->config.channels);
2745
2746 ret = pcm_write(out->pcm, out->convert_buffer,
2747 (out->config.period_size *
2748 out->config.channels *
2749 format_to_bitwidth_table[out->hal_op_format]));
2750 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002751 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302752 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002753
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002754 release_out_focus(out);
2755
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302756 if (ret < 0)
2757 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302758 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2759 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2760 else
2761 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002762 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 }
2764
2765exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302766 /* ToDo: There may be a corner case when SSR happens back to back during
2767 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302768 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302769 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302770 }
2771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 pthread_mutex_unlock(&out->lock);
2773
2774 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002775 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002776 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302777 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302778 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302779 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302780 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302781 out->standby = true;
2782 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302784 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302785 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786 }
2787 return bytes;
2788}
2789
2790static int out_get_render_position(const struct audio_stream_out *stream,
2791 uint32_t *dsp_frames)
2792{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302794 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002795
2796 if (dsp_frames == NULL)
2797 return -EINVAL;
2798
2799 *dsp_frames = 0;
2800 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002801 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302802
2803 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2804 * this operation and adev_close_output_stream(where out gets reset).
2805 */
2806 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2807 *dsp_frames = get_actual_pcm_frames_rendered(out);
2808 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2809 return 0;
2810 }
2811
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002812 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302813 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302814 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002815 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302816 if (ret < 0)
2817 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302819 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002820 }
2821 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302822 if (-ENETRESET == ret) {
2823 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2824 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2825 return -EINVAL;
2826 } else if(ret < 0) {
2827 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2828 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302829 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2830 /*
2831 * Handle corner case where compress session is closed during SSR
2832 * and timestamp is queried
2833 */
2834 ALOGE(" ERROR: sound card not active, return error");
2835 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302836 } else {
2837 return 0;
2838 }
Zhou Song32a556e2015-05-05 10:46:56 +08002839 } else if (audio_is_linear_pcm(out->format)) {
2840 *dsp_frames = out->written;
2841 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 } else
2843 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844}
2845
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002846static int out_add_audio_effect(const struct audio_stream *stream __unused,
2847 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848{
2849 return 0;
2850}
2851
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002852static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2853 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854{
2855 return 0;
2856}
2857
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002858static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2859 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860{
2861 return -EINVAL;
2862}
2863
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002864static int out_get_presentation_position(const struct audio_stream_out *stream,
2865 uint64_t *frames, struct timespec *timestamp)
2866{
2867 struct stream_out *out = (struct stream_out *)stream;
2868 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002869 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002870
Ashish Jain5106d362016-05-11 19:23:33 +05302871 /* below piece of code is not guarded against any lock because audioFliner serializes
2872 * this operation and adev_close_output_stream( where out gets reset).
2873 */
2874 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2875 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2876 *frames = get_actual_pcm_frames_rendered(out);
2877 /* this is the best we can do */
2878 clock_gettime(CLOCK_MONOTONIC, timestamp);
2879 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2880 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2881 return 0;
2882 }
2883
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002884 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002885
Ashish Jain5106d362016-05-11 19:23:33 +05302886 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2887 ret = compress_get_tstamp(out->compr, &dsp_frames,
2888 &out->sample_rate);
2889 ALOGVV("%s rendered frames %ld sample_rate %d",
2890 __func__, dsp_frames, out->sample_rate);
2891 *frames = dsp_frames;
2892 if (ret < 0)
2893 ret = -errno;
2894 if (-ENETRESET == ret) {
2895 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2896 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2897 ret = -EINVAL;
2898 } else
2899 ret = 0;
2900 /* this is the best we can do */
2901 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002902 } else {
2903 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002904 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002905 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2906 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002907 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002908 // This adjustment accounts for buffering after app processor.
2909 // It is based on estimated DSP latency per use case, rather than exact.
2910 signed_frames -=
2911 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2912
Eric Laurent949a0892013-09-20 09:20:13 -07002913 // It would be unusual for this value to be negative, but check just in case ...
2914 if (signed_frames >= 0) {
2915 *frames = signed_frames;
2916 ret = 0;
2917 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002918 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302919 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2920 *frames = out->written;
2921 clock_gettime(CLOCK_MONOTONIC, timestamp);
2922 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002923 }
2924 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002925 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002926 return ret;
2927}
2928
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002929static int out_set_callback(struct audio_stream_out *stream,
2930 stream_callback_t callback, void *cookie)
2931{
2932 struct stream_out *out = (struct stream_out *)stream;
2933
2934 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002935 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002936 out->offload_callback = callback;
2937 out->offload_cookie = cookie;
2938 pthread_mutex_unlock(&out->lock);
2939 return 0;
2940}
2941
2942static int out_pause(struct audio_stream_out* stream)
2943{
2944 struct stream_out *out = (struct stream_out *)stream;
2945 int status = -ENOSYS;
2946 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002947 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002948 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002949 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302951 struct audio_device *adev = out->dev;
2952 int snd_scard_state = get_snd_card_state(adev);
2953
2954 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2955 status = compress_pause(out->compr);
2956
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002958
Mingming Yin21854652016-04-13 11:54:02 -07002959 if (audio_extn_passthru_is_active()) {
2960 ALOGV("offload use case, pause passthru");
2961 audio_extn_passthru_on_pause(out);
2962 }
2963
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302964 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002965 audio_extn_dts_notify_playback_state(out->usecase, 0,
2966 out->sample_rate, popcount(out->channel_mask),
2967 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002968 }
2969 pthread_mutex_unlock(&out->lock);
2970 }
2971 return status;
2972}
2973
2974static int out_resume(struct audio_stream_out* stream)
2975{
2976 struct stream_out *out = (struct stream_out *)stream;
2977 int status = -ENOSYS;
2978 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002979 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002980 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002981 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002982 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002983 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302984 struct audio_device *adev = out->dev;
2985 int snd_scard_state = get_snd_card_state(adev);
2986
Mingming Yin21854652016-04-13 11:54:02 -07002987 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2988 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2989 pthread_mutex_lock(&out->dev->lock);
2990 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07002991 pthread_mutex_unlock(&out->dev->lock);
2992 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302993 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002994 }
2995 if (!status) {
2996 out->offload_state = OFFLOAD_STATE_PLAYING;
2997 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302998 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002999 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3000 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001 }
3002 pthread_mutex_unlock(&out->lock);
3003 }
3004 return status;
3005}
3006
3007static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3008{
3009 struct stream_out *out = (struct stream_out *)stream;
3010 int status = -ENOSYS;
3011 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003012 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003013 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003014 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3015 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3016 else
3017 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3018 pthread_mutex_unlock(&out->lock);
3019 }
3020 return status;
3021}
3022
3023static int out_flush(struct audio_stream_out* stream)
3024{
3025 struct stream_out *out = (struct stream_out *)stream;
3026 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003027 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003028 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003029 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303031 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003032 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003033 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034 return 0;
3035 }
3036 return -ENOSYS;
3037}
3038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039/** audio_stream_in implementation **/
3040static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3041{
3042 struct stream_in *in = (struct stream_in *)stream;
3043
3044 return in->config.rate;
3045}
3046
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003047static int in_set_sample_rate(struct audio_stream *stream __unused,
3048 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049{
3050 return -ENOSYS;
3051}
3052
3053static size_t in_get_buffer_size(const struct audio_stream *stream)
3054{
3055 struct stream_in *in = (struct stream_in *)stream;
3056
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003057 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3058 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003059 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3060 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003061
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003062 return in->config.period_size * in->af_period_multiplier *
3063 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064}
3065
3066static uint32_t in_get_channels(const struct audio_stream *stream)
3067{
3068 struct stream_in *in = (struct stream_in *)stream;
3069
3070 return in->channel_mask;
3071}
3072
3073static audio_format_t in_get_format(const struct audio_stream *stream)
3074{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003075 struct stream_in *in = (struct stream_in *)stream;
3076
3077 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078}
3079
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003080static int in_set_format(struct audio_stream *stream __unused,
3081 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082{
3083 return -ENOSYS;
3084}
3085
3086static int in_standby(struct audio_stream *stream)
3087{
3088 struct stream_in *in = (struct stream_in *)stream;
3089 struct audio_device *adev = in->dev;
3090 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303091 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3092 stream, in->usecase, use_case_table[in->usecase]);
3093
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003094 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003095 if (!in->standby && in->is_st_session) {
3096 ALOGD("%s: sound trigger pcm stop lab", __func__);
3097 audio_extn_sound_trigger_stop_lab(in);
3098 in->standby = 1;
3099 }
3100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003102 if (adev->adm_deregister_stream)
3103 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3104
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003105 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003107 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3108 voice_extn_compress_voip_close_input_stream(stream);
3109 ALOGD("VOIP input entered standby");
3110 } else {
3111 if (in->pcm) {
3112 pcm_close(in->pcm);
3113 in->pcm = NULL;
3114 }
3115 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003116 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003117 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118 }
3119 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003120 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 return status;
3122}
3123
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003124static int in_dump(const struct audio_stream *stream __unused,
3125 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126{
3127 return 0;
3128}
3129
3130static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3131{
3132 struct stream_in *in = (struct stream_in *)stream;
3133 struct audio_device *adev = in->dev;
3134 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003136 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303138 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 parms = str_parms_create_str(kvpairs);
3140
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303141 if (!parms)
3142 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003143 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003144 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003145
3146 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3147 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 val = atoi(value);
3149 /* no audio source uses val == 0 */
3150 if ((in->source != val) && (val != 0)) {
3151 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003152 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3153 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3154 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003155 (in->config.rate == 8000 || in->config.rate == 16000 ||
3156 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003157 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003158 err = voice_extn_compress_voip_open_input_stream(in);
3159 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003160 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003161 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003162 }
3163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 }
3165 }
3166
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003167 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3168 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003170 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 in->device = val;
3172 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003173 if (!in->standby && !in->is_st_session) {
3174 ALOGV("update input routing change");
3175 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003176 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003177 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178 }
3179 }
3180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003182 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183
3184 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303185error:
Eric Laurent994a6932013-07-17 11:51:42 -07003186 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 return ret;
3188}
3189
3190static char* in_get_parameters(const struct audio_stream *stream,
3191 const char *keys)
3192{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003193 struct stream_in *in = (struct stream_in *)stream;
3194 struct str_parms *query = str_parms_create_str(keys);
3195 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003196 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003197
3198 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003199 if (reply) {
3200 str_parms_destroy(reply);
3201 }
3202 if (query) {
3203 str_parms_destroy(query);
3204 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003205 ALOGE("in_get_parameters: failed to create query or reply");
3206 return NULL;
3207 }
3208
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003209 ALOGV("%s: enter: keys - %s", __func__, keys);
3210
3211 voice_extn_in_get_parameters(in, query, reply);
3212
3213 str = str_parms_to_str(reply);
3214 str_parms_destroy(query);
3215 str_parms_destroy(reply);
3216
3217 ALOGV("%s: exit: returns - %s", __func__, str);
3218 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219}
3220
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003221static int in_set_gain(struct audio_stream_in *stream __unused,
3222 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223{
3224 return 0;
3225}
3226
3227static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3228 size_t bytes)
3229{
3230 struct stream_in *in = (struct stream_in *)stream;
3231 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303232 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303233 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303234 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003236 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303237
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003238 if (in->is_st_session) {
3239 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3240 /* Read from sound trigger HAL */
3241 audio_extn_sound_trigger_read(in, buffer, bytes);
3242 pthread_mutex_unlock(&in->lock);
3243 return bytes;
3244 }
3245
Ashish Jainbbce4322016-02-16 13:25:27 +05303246 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003247 ALOGD(" %s: sound card is not active/SSR state", __func__);
3248 ret= -EIO;;
3249 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303250 }
3251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003253 pthread_mutex_lock(&adev->lock);
3254 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3255 ret = voice_extn_compress_voip_start_input_stream(in);
3256 else
3257 ret = start_input_stream(in);
3258 pthread_mutex_unlock(&adev->lock);
3259 if (ret != 0) {
3260 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 }
3262 in->standby = 0;
3263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003265 // what's the duration requested by the client?
3266 long ns = 0;
3267
3268 if (in->config.rate)
3269 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3270 in->config.rate;
3271
3272 request_in_focus(in, ns);
3273 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303276 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003277 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303278 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003279 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003280 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003281 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303282 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003283 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303284 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3285 if (bytes % 4 == 0) {
3286 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3287 int_buf_stream = buffer;
3288 for (size_t itt=0; itt < bytes/4 ; itt++) {
3289 int_buf_stream[itt] >>= 8;
3290 }
3291 } else {
3292 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3293 ret = -EINVAL;
3294 goto exit;
3295 }
3296 } if (ret < 0) {
3297 ret = -errno;
3298 }
3299 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 }
3301
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003302 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 /*
3305 * Instead of writing zeroes here, we could trust the hardware
3306 * to always provide zeroes when muted.
3307 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303308 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3309 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310 memset(buffer, 0, bytes);
3311
3312exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303313 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303314 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003315 if (-ENETRESET == ret)
3316 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 pthread_mutex_unlock(&in->lock);
3319
3320 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303321 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303322 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303323 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303324 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303325 in->standby = true;
3326 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303327 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003329 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303330 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303331 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332 }
3333 return bytes;
3334}
3335
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003336static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337{
3338 return 0;
3339}
3340
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003341static int add_remove_audio_effect(const struct audio_stream *stream,
3342 effect_handle_t effect,
3343 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003345 struct stream_in *in = (struct stream_in *)stream;
3346 int status = 0;
3347 effect_descriptor_t desc;
3348
3349 status = (*effect)->get_descriptor(effect, &desc);
3350 if (status != 0)
3351 return status;
3352
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003353 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003354 pthread_mutex_lock(&in->dev->lock);
3355 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3356 in->enable_aec != enable &&
3357 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3358 in->enable_aec = enable;
3359 if (!in->standby)
3360 select_devices(in->dev, in->usecase);
3361 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003362 if (in->enable_ns != enable &&
3363 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3364 in->enable_ns = enable;
3365 if (!in->standby)
3366 select_devices(in->dev, in->usecase);
3367 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003368 pthread_mutex_unlock(&in->dev->lock);
3369 pthread_mutex_unlock(&in->lock);
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 return 0;
3372}
3373
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003374static int in_add_audio_effect(const struct audio_stream *stream,
3375 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376{
Eric Laurent994a6932013-07-17 11:51:42 -07003377 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003378 return add_remove_audio_effect(stream, effect, true);
3379}
3380
3381static int in_remove_audio_effect(const struct audio_stream *stream,
3382 effect_handle_t effect)
3383{
Eric Laurent994a6932013-07-17 11:51:42 -07003384 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003385 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386}
3387
3388static int adev_open_output_stream(struct audio_hw_device *dev,
3389 audio_io_handle_t handle,
3390 audio_devices_t devices,
3391 audio_output_flags_t flags,
3392 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003393 struct audio_stream_out **stream_out,
3394 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395{
3396 struct audio_device *adev = (struct audio_device *)dev;
3397 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303398 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003399 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303402
3403 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3404 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003405 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303406 return -EINVAL;
3407 }
3408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3410
Mingming Yin3a941d42016-02-17 18:08:05 -08003411 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3412 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303413 devices, flags, &out->stream);
3414
3415
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003416 if (!out) {
3417 return -ENOMEM;
3418 }
3419
Haynes Mathew George204045b2015-02-25 20:32:03 -08003420 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003421 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003422 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3423
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 if (devices == AUDIO_DEVICE_NONE)
3425 devices = AUDIO_DEVICE_OUT_SPEAKER;
3426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427 out->flags = flags;
3428 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003429 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003430 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003431 out->sample_rate = config->sample_rate;
3432 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3433 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003434 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003435 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003436 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303437 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438
Mingming Yin3a941d42016-02-17 18:08:05 -08003439 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3440 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3441 pthread_mutex_lock(&adev->lock);
3442 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3443 ret = read_hdmi_sink_caps(out);
3444 pthread_mutex_unlock(&adev->lock);
3445 if (ret != 0) {
3446 if (ret == -ENOSYS) {
3447 /* ignore and go with default */
3448 ret = 0;
3449 } else {
3450 ALOGE("error reading hdmi sink caps");
3451 goto error_open;
3452 }
3453 }
3454 }
3455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003456 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003457 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303458 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3459 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003460 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3461 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3462
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003463 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003464 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3465 /*
3466 * Do not handle stereo output in Multi-channel cases
3467 * Stereo case is handled in normal playback path
3468 */
3469 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3470 ret = AUDIO_CHANNEL_OUT_STEREO;
3471 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003472
3473 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3474 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003475 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003476 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003477 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003478
3479 if (config->sample_rate == 0)
3480 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3481 if (config->channel_mask == 0)
3482 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003483 if (config->format == 0)
3484 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003485
3486 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003487 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003488 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3490 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003492 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003494 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3495 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003496 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003497 ret = voice_extn_compress_voip_open_output_stream(out);
3498 if (ret != 0) {
3499 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3500 __func__, ret);
3501 goto error_open;
3502 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003503 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3504 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3505
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003506 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3507 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3508 ALOGE("%s: Unsupported Offload information", __func__);
3509 ret = -EINVAL;
3510 goto error_open;
3511 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003512
Mingming Yin3a941d42016-02-17 18:08:05 -08003513 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003514 if(config->offload_info.format == 0)
3515 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003516 if (config->offload_info.sample_rate == 0)
3517 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003518 }
3519
Mingming Yin90310102013-11-13 16:57:00 -08003520 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303521 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003522 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003523 ret = -EINVAL;
3524 goto error_open;
3525 }
3526
3527 out->compr_config.codec = (struct snd_codec *)
3528 calloc(1, sizeof(struct snd_codec));
3529
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003530 if (!out->compr_config.codec) {
3531 ret = -ENOMEM;
3532 goto error_open;
3533 }
3534
vivek mehta0ea887a2015-08-26 14:01:20 -07003535 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303536 out->stream.pause = out_pause;
3537 out->stream.flush = out_flush;
3538 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003539 out->usecase = get_offload_usecase(adev, true);
3540 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003541 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003542 out->stream.set_callback = out_set_callback;
3543 out->stream.pause = out_pause;
3544 out->stream.resume = out_resume;
3545 out->stream.drain = out_drain;
3546 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003547 out->usecase = get_offload_usecase(adev, false);
3548 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003549 }
vivek mehta446c3962015-09-14 10:57:35 -07003550
3551 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003552 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3553 config->format == 0 && config->sample_rate == 0 &&
3554 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003555 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003556 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3557 } else {
3558 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3559 ret = -EEXIST;
3560 goto error_open;
3561 }
vivek mehta446c3962015-09-14 10:57:35 -07003562 }
3563
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003564 if (config->offload_info.channel_mask)
3565 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003566 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003567 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003568 config->offload_info.channel_mask = config->channel_mask;
3569 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003570 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003571 out->sample_rate = config->offload_info.sample_rate;
3572
Mingming Yin3ee55c62014-08-04 14:23:35 -07003573 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003574
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303575 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3576 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3577 audio_extn_dolby_send_ddp_endp_params(adev);
3578 audio_extn_dolby_set_dmid(adev);
3579 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003580
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003581 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003582 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 out->compr_config.codec->bit_rate =
3584 config->offload_info.bit_rate;
3585 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303586 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303588 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003589 /*TODO: Do we need to change it for passthrough */
3590 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003591
Manish Dewangana6fc5442015-08-24 20:30:31 +05303592 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3593 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3594 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3595 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303596
3597 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3598 AUDIO_FORMAT_PCM) {
3599
3600 /*Based on platform support, configure appropriate alsa format for corresponding
3601 *hal input format.
3602 */
3603 out->compr_config.codec->format = hal_format_to_alsa(
3604 config->offload_info.format);
3605
Ashish Jain83a6cc22016-06-28 14:34:17 +05303606 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303607 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303608 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303609
3610 /*for direct PCM playback populate bit_width based on selected alsa format as
3611 *hal input format and alsa format might differ based on platform support.
3612 */
3613 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303614 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303615
3616 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3617
3618 /* Check if alsa session is configured with the same format as HAL input format,
3619 * if not then derive correct fragment size needed to accomodate the
3620 * conversion of HAL input format to alsa format.
3621 */
3622 audio_extn_utils_update_direct_pcm_fragment_size(out);
3623
3624 /*if hal input and output fragment size is different this indicates HAL input format is
3625 *not same as the alsa format
3626 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303627 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303628 /*Allocate a buffer to convert input data to the alsa configured format.
3629 *size of convert buffer is equal to the size required to hold one fragment size
3630 *worth of pcm data, this is because flinger does not write more than fragment_size
3631 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303632 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3633 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303634 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3635 ret = -ENOMEM;
3636 goto error_open;
3637 }
3638 }
3639 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3640 out->compr_config.fragment_size =
3641 audio_extn_passthru_get_buffer_size(&config->offload_info);
3642 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3643 } else {
3644 out->compr_config.fragment_size =
3645 platform_get_compress_offload_buffer_size(&config->offload_info);
3646 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3647 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003648
Amit Shekhar6f461b12014-08-01 14:52:58 -07003649 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303650 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003651
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3653 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003654
Alexy Josephaa54c872014-12-03 02:46:47 -08003655
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003656 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303657 out->send_next_track_params = false;
3658 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003659 out->offload_state = OFFLOAD_STATE_IDLE;
3660 out->playback_started = 0;
3661
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003662 audio_extn_dts_create_state_notifier_node(out->usecase);
3663
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 create_offload_callback_thread(out);
3665 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3666 __func__, config->offload_info.version,
3667 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303668
3669 /* Disable gapless if any of the following is true
3670 * passthrough playback
3671 * AV playback
3672 * Direct PCM playback
3673 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303674 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303675 config->offload_info.has_video ||
3676 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3677 check_and_set_gapless_mode(adev, false);
3678 } else
3679 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003680
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303681 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003682 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3683 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003684 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303685 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003686 if (ret != 0) {
3687 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3688 __func__, ret);
3689 goto error_open;
3690 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003691 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3692 if (config->sample_rate == 0)
3693 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3694 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3695 config->sample_rate != 8000) {
3696 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3697 ret = -EINVAL;
3698 goto error_open;
3699 }
3700 out->sample_rate = config->sample_rate;
3701 out->config.rate = config->sample_rate;
3702 if (config->format == AUDIO_FORMAT_DEFAULT)
3703 config->format = AUDIO_FORMAT_PCM_16_BIT;
3704 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3705 config->format = AUDIO_FORMAT_PCM_16_BIT;
3706 ret = -EINVAL;
3707 goto error_open;
3708 }
3709 out->format = config->format;
3710 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3711 out->config = pcm_config_afe_proxy_playback;
3712 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003713 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303714 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3715 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003716 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3717 out->flags);
3718 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303719 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3720 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3721 out->config = pcm_config_low_latency;
3722 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3723 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3724 out->config = pcm_config_deep_buffer;
3725 } else {
3726 /* primary path is the default path selected if no other outputs are available/suitable */
3727 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3728 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3729 }
3730 out->hal_ip_format = format = out->format;
3731 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3732 out->hal_op_format = pcm_format_to_hal(out->config.format);
3733 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3734 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003735 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303736 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3737 if (out->hal_ip_format != out->hal_op_format) {
3738 uint32_t buffer_size = out->config.period_size *
3739 format_to_bitwidth_table[out->hal_op_format] *
3740 out->config.channels;
3741 out->convert_buffer = calloc(1, buffer_size);
3742 if (out->convert_buffer == NULL){
3743 ALOGE("Allocation failed for convert buffer for size %d",
3744 out->compr_config.fragment_size);
3745 ret = -ENOMEM;
3746 goto error_open;
3747 }
3748 ALOGD("Convert buffer allocated of size %d", buffer_size);
3749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 }
3751
Ashish Jain83a6cc22016-06-28 14:34:17 +05303752 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3753 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3754
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003755 /* TODO remove this hardcoding and check why width is zero*/
3756 if (out->bit_width == 0)
3757 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003758 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3759 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003760 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303761 out->bit_width, out->channel_mask,
3762 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003763 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3764 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3765 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003766 if(adev->primary_output == NULL)
3767 adev->primary_output = out;
3768 else {
3769 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003770 ret = -EEXIST;
3771 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003772 }
3773 }
3774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 /* Check if this usecase is already existing */
3776 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003777 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3778 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003781 ret = -EEXIST;
3782 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 }
3784 pthread_mutex_unlock(&adev->lock);
3785
3786 out->stream.common.get_sample_rate = out_get_sample_rate;
3787 out->stream.common.set_sample_rate = out_set_sample_rate;
3788 out->stream.common.get_buffer_size = out_get_buffer_size;
3789 out->stream.common.get_channels = out_get_channels;
3790 out->stream.common.get_format = out_get_format;
3791 out->stream.common.set_format = out_set_format;
3792 out->stream.common.standby = out_standby;
3793 out->stream.common.dump = out_dump;
3794 out->stream.common.set_parameters = out_set_parameters;
3795 out->stream.common.get_parameters = out_get_parameters;
3796 out->stream.common.add_audio_effect = out_add_audio_effect;
3797 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3798 out->stream.get_latency = out_get_latency;
3799 out->stream.set_volume = out_set_volume;
3800 out->stream.write = out_write;
3801 out->stream.get_render_position = out_get_render_position;
3802 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003803 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003805 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003807 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003808 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809
3810 config->format = out->stream.common.get_format(&out->stream.common);
3811 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3812 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3813
3814 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303815 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003816 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003817
3818 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3819 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3820 popcount(out->channel_mask), out->playback_started);
3821
Eric Laurent994a6932013-07-17 11:51:42 -07003822 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003824
3825error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303826 if (out->convert_buffer)
3827 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003828 free(out);
3829 *stream_out = NULL;
3830 ALOGD("%s: exit: ret %d", __func__, ret);
3831 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832}
3833
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003834static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 struct audio_stream_out *stream)
3836{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003837 struct stream_out *out = (struct stream_out *)stream;
3838 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003839 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303841 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3842
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003843 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303844 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003845 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303846 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003847 if(ret != 0)
3848 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3849 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003850 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003851 out_standby(&stream->common);
3852
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003853 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003854 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003855 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003856 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003857 if (out->compr_config.codec != NULL)
3858 free(out->compr_config.codec);
3859 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003860
Ashish Jain83a6cc22016-06-28 14:34:17 +05303861 if (out->convert_buffer != NULL) {
3862 free(out->convert_buffer);
3863 out->convert_buffer = NULL;
3864 }
3865
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003866 if (adev->voice_tx_output == out)
3867 adev->voice_tx_output = NULL;
3868
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003869 pthread_cond_destroy(&out->cond);
3870 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003872 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873}
3874
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003875static void close_compress_sessions(struct audio_device *adev)
3876{
Mingming Yin7b762e72015-03-04 13:47:32 -08003877 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303878 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003879 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003880 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303881
3882 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003883 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303884 if (is_offload_usecase(usecase->id)) {
3885 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003886 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3887 out = usecase->stream.out;
3888 pthread_mutex_unlock(&adev->lock);
3889 out_standby(&out->stream.common);
3890 pthread_mutex_lock(&adev->lock);
3891 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303892 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003893 }
3894 pthread_mutex_unlock(&adev->lock);
3895}
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3898{
3899 struct audio_device *adev = (struct audio_device *)dev;
3900 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003902 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003903 int ret;
3904 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003906 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303909 if (!parms)
3910 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003911 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3912 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303913 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303914 if (strstr(snd_card_status, "OFFLINE")) {
3915 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303916 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003917 //close compress sessions on OFFLINE status
3918 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303919 } else if (strstr(snd_card_status, "ONLINE")) {
3920 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303921 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003922 //send dts hpx license if enabled
3923 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303924 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303925 }
3926
3927 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003928 status = voice_set_parameters(adev, parms);
3929 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003930 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003932 status = platform_set_parameters(adev->platform, parms);
3933 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003934 goto done;
3935
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003936 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3937 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003938 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3940 adev->bluetooth_nrec = true;
3941 else
3942 adev->bluetooth_nrec = false;
3943 }
3944
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003945 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3946 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3948 adev->screen_off = false;
3949 else
3950 adev->screen_off = true;
3951 }
3952
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003953 ret = str_parms_get_int(parms, "rotation", &val);
3954 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003955 bool reverse_speakers = false;
3956 switch(val) {
3957 // FIXME: note that the code below assumes that the speakers are in the correct placement
3958 // relative to the user when the device is rotated 90deg from its default rotation. This
3959 // assumption is device-specific, not platform-specific like this code.
3960 case 270:
3961 reverse_speakers = true;
3962 break;
3963 case 0:
3964 case 90:
3965 case 180:
3966 break;
3967 default:
3968 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003969 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003970 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003971 if (status == 0) {
3972 if (adev->speaker_lr_swap != reverse_speakers) {
3973 adev->speaker_lr_swap = reverse_speakers;
3974 // only update the selected device if there is active pcm playback
3975 struct audio_usecase *usecase;
3976 struct listnode *node;
3977 list_for_each(node, &adev->usecase_list) {
3978 usecase = node_to_item(node, struct audio_usecase, list);
3979 if (usecase->type == PCM_PLAYBACK) {
3980 select_devices(adev, usecase->id);
3981 break;
3982 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003983 }
3984 }
3985 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003986 }
3987
Mingming Yin514a8bc2014-07-29 15:22:21 -07003988 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3989 if (ret >= 0) {
3990 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3991 adev->bt_wb_speech_enabled = true;
3992 else
3993 adev->bt_wb_speech_enabled = false;
3994 }
3995
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003996 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3997 if (ret >= 0) {
3998 val = atoi(value);
3999 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4000 ALOGV("cache new edid");
4001 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004002 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4003 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004004 /*
4005 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4006 * Per AudioPolicyManager, USB device is higher priority than WFD.
4007 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4008 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4009 * starting voice call on USB
4010 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004011 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4012 if (ret >= 0) {
4013 audio_extn_usb_add_device(val, atoi(value));
4014 }
vivek mehta344576a2016-04-12 18:56:03 -07004015 ALOGV("detected USB connect .. disable proxy");
4016 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004017 }
4018 }
4019
4020 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4021 if (ret >= 0) {
4022 val = atoi(value);
4023 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4024 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004025 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004026 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4027 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4028 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4029 if (ret >= 0) {
4030 audio_extn_usb_remove_device(val, atoi(value));
4031 }
vivek mehta344576a2016-04-12 18:56:03 -07004032 ALOGV("detected USB disconnect .. enable proxy");
4033 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004034 }
4035 }
4036
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004037 audio_extn_set_parameters(adev, parms);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304038 // reconfigure should be done only after updating a2dpstate in audio extn
4039 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4040 if (ret >= 0) {
4041 struct audio_usecase *usecase;
4042 struct listnode *node;
4043 list_for_each(node, &adev->usecase_list) {
4044 usecase = node_to_item(node, struct audio_usecase, list);
4045 if ((usecase->type == PCM_PLAYBACK) &&
4046 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4047 ALOGD("reconfigure a2dp... forcing device switch");
4048 //force device switch to re configure encoder
4049 select_devices(adev, usecase->id);
4050 break;
4051 }
4052 }
4053 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004054
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004055done:
4056 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004057 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304058error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004059 ALOGV("%s: exit with code(%d)", __func__, status);
4060 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061}
4062
4063static char* adev_get_parameters(const struct audio_hw_device *dev,
4064 const char *keys)
4065{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004066 struct audio_device *adev = (struct audio_device *)dev;
4067 struct str_parms *reply = str_parms_create();
4068 struct str_parms *query = str_parms_create_str(keys);
4069 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304070 char value[256] = {0};
4071 int ret = 0;
4072
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004073 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004074 if (reply) {
4075 str_parms_destroy(reply);
4076 }
4077 if (query) {
4078 str_parms_destroy(query);
4079 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004080 ALOGE("adev_get_parameters: failed to create query or reply");
4081 return NULL;
4082 }
4083
Naresh Tannirud7205b62014-06-20 02:54:48 +05304084 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4085 sizeof(value));
4086 if (ret >=0) {
4087 int val = 1;
4088 pthread_mutex_lock(&adev->snd_card_status.lock);
4089 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4090 val = 0;
4091 pthread_mutex_unlock(&adev->snd_card_status.lock);
4092 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4093 goto exit;
4094 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004095
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004096 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004097 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004098 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004099 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304100 pthread_mutex_unlock(&adev->lock);
4101
Naresh Tannirud7205b62014-06-20 02:54:48 +05304102exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004103 str = str_parms_to_str(reply);
4104 str_parms_destroy(query);
4105 str_parms_destroy(reply);
4106
4107 ALOGV("%s: exit: returns - %s", __func__, str);
4108 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109}
4110
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004111static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112{
4113 return 0;
4114}
4115
4116static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4117{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004118 int ret;
4119 struct audio_device *adev = (struct audio_device *)dev;
4120 pthread_mutex_lock(&adev->lock);
4121 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004122 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004123 pthread_mutex_unlock(&adev->lock);
4124 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125}
4126
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004127static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4128 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129{
4130 return -ENOSYS;
4131}
4132
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004133static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4134 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135{
4136 return -ENOSYS;
4137}
4138
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004139static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4140 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141{
4142 return -ENOSYS;
4143}
4144
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004145static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4146 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147{
4148 return -ENOSYS;
4149}
4150
4151static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4152{
4153 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155 pthread_mutex_lock(&adev->lock);
4156 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004157 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004159 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004160 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004161 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004162 adev->current_call_output = NULL;
4163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 }
4165 pthread_mutex_unlock(&adev->lock);
4166 return 0;
4167}
4168
4169static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4170{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004171 int ret;
4172
4173 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004174 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004175 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4176 pthread_mutex_unlock(&adev->lock);
4177
4178 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179}
4180
4181static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4182{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004183 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 return 0;
4185}
4186
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004187static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 const struct audio_config *config)
4189{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004190 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004192 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4193 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194}
4195
4196static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004197 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 audio_devices_t devices,
4199 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004200 struct audio_stream_in **stream_in,
4201 audio_input_flags_t flags __unused,
4202 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004203 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204{
4205 struct audio_device *adev = (struct audio_device *)dev;
4206 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004207 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004208 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004209 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304212 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4213 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216
4217 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004218
4219 if (!in) {
4220 ALOGE("failed to allocate input stream");
4221 return -ENOMEM;
4222 }
4223
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304224 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304225 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4226 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004227 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004228 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004230 in->stream.common.get_sample_rate = in_get_sample_rate;
4231 in->stream.common.set_sample_rate = in_set_sample_rate;
4232 in->stream.common.get_buffer_size = in_get_buffer_size;
4233 in->stream.common.get_channels = in_get_channels;
4234 in->stream.common.get_format = in_get_format;
4235 in->stream.common.set_format = in_set_format;
4236 in->stream.common.standby = in_standby;
4237 in->stream.common.dump = in_dump;
4238 in->stream.common.set_parameters = in_set_parameters;
4239 in->stream.common.get_parameters = in_get_parameters;
4240 in->stream.common.add_audio_effect = in_add_audio_effect;
4241 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4242 in->stream.set_gain = in_set_gain;
4243 in->stream.read = in_read;
4244 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4245
4246 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004247 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249 in->standby = 1;
4250 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004251 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004252 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253
4254 /* Update config params with the requested sample rate and channels */
4255 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004256 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4257 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4258 is_low_latency = true;
4259#if LOW_LATENCY_CAPTURE_USE_CASE
4260 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4261#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004262 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004263 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004264
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004265 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004266 if (in->realtime) {
4267 in->config = pcm_config_audio_capture_rt;
4268 in->sample_rate = in->config.rate;
4269 in->af_period_multiplier = af_period_multiplier;
4270 } else {
4271 in->config = pcm_config_audio_capture;
4272 in->config.rate = config->sample_rate;
4273 in->sample_rate = config->sample_rate;
4274 in->af_period_multiplier = 1;
4275 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304276 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004278 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304279 if (adev->mode != AUDIO_MODE_IN_CALL) {
4280 ret = -EINVAL;
4281 goto err_open;
4282 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004283 if (config->sample_rate == 0)
4284 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4285 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4286 config->sample_rate != 8000) {
4287 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4288 ret = -EINVAL;
4289 goto err_open;
4290 }
4291 if (config->format == AUDIO_FORMAT_DEFAULT)
4292 config->format = AUDIO_FORMAT_PCM_16_BIT;
4293 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4294 config->format = AUDIO_FORMAT_PCM_16_BIT;
4295 ret = -EINVAL;
4296 goto err_open;
4297 }
4298
4299 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4300 in->config = pcm_config_afe_proxy_record;
4301 in->config.channels = channel_count;
4302 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304303 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304304 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4305 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004306 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004307 audio_extn_compr_cap_format_supported(config->format) &&
4308 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004309 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004310 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304311 /* restrict 24 bit capture for unprocessed source only
4312 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4313 */
4314 if (config->format == AUDIO_FORMAT_DEFAULT) {
4315 config->format = AUDIO_FORMAT_PCM_16_BIT;
4316 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4317 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4318 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4319 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4320 bool ret_error = false;
4321 in->bit_width = 24;
4322 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4323 from HAL is 24_packed and 8_24
4324 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4325 24_packed return error indicating supported format is 24_packed
4326 *> In case of any other source requesting 24 bit or float return error
4327 indicating format supported is 16 bit only.
4328
4329 on error flinger will retry with supported format passed
4330 */
4331 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4332 (source != AUDIO_SOURCE_CAMCORDER)) {
4333 config->format = AUDIO_FORMAT_PCM_16_BIT;
4334 if( config->sample_rate > 48000)
4335 config->sample_rate = 48000;
4336 ret_error = true;
4337 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4338 in->config.format = PCM_FORMAT_S24_3LE;
4339 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4340 in->config.format = PCM_FORMAT_S24_LE;
4341 } else {
4342 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4343 ret_error = true;
4344 }
4345
4346 if (ret_error) {
4347 ret = -EINVAL;
4348 goto err_open;
4349 }
4350 }
4351
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004352 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004353 if (!in->realtime) {
4354 in->format = config->format;
4355 frame_size = audio_stream_in_frame_size(&in->stream);
4356 buffer_size = get_input_buffer_size(config->sample_rate,
4357 config->format,
4358 channel_count,
4359 is_low_latency);
4360 in->config.period_size = buffer_size / frame_size;
4361 }
4362
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004363 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4364 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4365 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004366 (in->config.rate == 8000 || in->config.rate == 16000 ||
4367 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004368 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4369 voice_extn_compress_voip_open_input_stream(in);
4370 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004371 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004373 /* This stream could be for sound trigger lab,
4374 get sound trigger pcm if present */
4375 audio_extn_sound_trigger_check_and_get_session(in);
4376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004378 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004379 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
4381err_open:
4382 free(in);
4383 *stream_in = NULL;
4384 return ret;
4385}
4386
4387static void adev_close_input_stream(struct audio_hw_device *dev,
4388 struct audio_stream_in *stream)
4389{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004390 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004391 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004392 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304393
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304394 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004395
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304396 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004397 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304398
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004399 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304400 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004401 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304402 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004403 if (ret != 0)
4404 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4405 __func__, ret);
4406 } else
4407 in_standby(&stream->common);
4408
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004409 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004410 audio_extn_ssr_deinit();
4411 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412
Mingming Yine62d7842013-10-25 16:26:03 -07004413 if(audio_extn_compr_cap_enabled() &&
4414 audio_extn_compr_cap_format_supported(in->config.format))
4415 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004416
Mingming Yinfd7607b2016-01-22 12:48:44 -08004417 if (in->is_st_session) {
4418 ALOGV("%s: sound trigger pcm stop lab", __func__);
4419 audio_extn_sound_trigger_stop_lab(in);
4420 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004421 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 return;
4423}
4424
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004425static int adev_dump(const audio_hw_device_t *device __unused,
4426 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427{
4428 return 0;
4429}
4430
4431static int adev_close(hw_device_t *device)
4432{
4433 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004434
4435 if (!adev)
4436 return 0;
4437
4438 pthread_mutex_lock(&adev_init_lock);
4439
4440 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004441 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004442 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004443 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004444 audio_route_free(adev->audio_route);
4445 free(adev->snd_dev_ref_cnt);
4446 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004447 if (adev->adm_deinit)
4448 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004449 free(device);
4450 adev = NULL;
4451 }
4452 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 return 0;
4455}
4456
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004457/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4458 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4459 * just that it _might_ work.
4460 */
4461static int period_size_is_plausible_for_low_latency(int period_size)
4462{
4463 switch (period_size) {
4464 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004465 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004466 case 240:
4467 case 320:
4468 case 480:
4469 return 1;
4470 default:
4471 return 0;
4472 }
4473}
4474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475static int adev_open(const hw_module_t *module, const char *name,
4476 hw_device_t **device)
4477{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004478 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4480
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004481 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004482 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004483 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004484 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004485 ALOGD("%s: returning existing instance of adev", __func__);
4486 ALOGD("%s: exit", __func__);
4487 pthread_mutex_unlock(&adev_init_lock);
4488 return 0;
4489 }
4490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491 adev = calloc(1, sizeof(struct audio_device));
4492
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004493 if (!adev) {
4494 pthread_mutex_unlock(&adev_init_lock);
4495 return -ENOMEM;
4496 }
4497
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004498 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4501 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4502 adev->device.common.module = (struct hw_module_t *)module;
4503 adev->device.common.close = adev_close;
4504
4505 adev->device.init_check = adev_init_check;
4506 adev->device.set_voice_volume = adev_set_voice_volume;
4507 adev->device.set_master_volume = adev_set_master_volume;
4508 adev->device.get_master_volume = adev_get_master_volume;
4509 adev->device.set_master_mute = adev_set_master_mute;
4510 adev->device.get_master_mute = adev_get_master_mute;
4511 adev->device.set_mode = adev_set_mode;
4512 adev->device.set_mic_mute = adev_set_mic_mute;
4513 adev->device.get_mic_mute = adev_get_mic_mute;
4514 adev->device.set_parameters = adev_set_parameters;
4515 adev->device.get_parameters = adev_get_parameters;
4516 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4517 adev->device.open_output_stream = adev_open_output_stream;
4518 adev->device.close_output_stream = adev_close_output_stream;
4519 adev->device.open_input_stream = adev_open_input_stream;
4520 adev->device.close_input_stream = adev_close_input_stream;
4521 adev->device.dump = adev_dump;
4522
4523 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004525 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004526 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004528 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004529 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004530 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004531 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004532 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004533 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004534 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004535 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004536 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304537 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304538 adev->perf_lock_opts[0] = 0x101;
4539 adev->perf_lock_opts[1] = 0x20E;
4540 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304541
4542 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4543 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004545 adev->platform = platform_init(adev);
4546 if (!adev->platform) {
4547 free(adev->snd_dev_ref_cnt);
4548 free(adev);
4549 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4550 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004551 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004552 return -EINVAL;
4553 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004554
Naresh Tanniru4c630392014-05-12 01:05:52 +05304555 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4556
Eric Laurentc4aef752013-09-12 17:45:53 -07004557 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4558 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4559 if (adev->visualizer_lib == NULL) {
4560 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4561 } else {
4562 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4563 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004564 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004565 "visualizer_hal_start_output");
4566 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004567 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004568 "visualizer_hal_stop_output");
4569 }
4570 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004571 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004572 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004573
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004574 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4575 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4576 if (adev->offload_effects_lib == NULL) {
4577 ALOGE("%s: DLOPEN failed for %s", __func__,
4578 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4579 } else {
4580 ALOGV("%s: DLOPEN successful for %s", __func__,
4581 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4582 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304583 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004584 "offload_effects_bundle_hal_start_output");
4585 adev->offload_effects_stop_output =
4586 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4587 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004588 adev->offload_effects_set_hpx_state =
4589 (int (*)(bool))dlsym(adev->offload_effects_lib,
4590 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304591 adev->offload_effects_get_parameters =
4592 (void (*)(struct str_parms *, struct str_parms *))
4593 dlsym(adev->offload_effects_lib,
4594 "offload_effects_bundle_get_parameters");
4595 adev->offload_effects_set_parameters =
4596 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4597 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004598 }
4599 }
4600
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004601 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4602 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4603 if (adev->adm_lib == NULL) {
4604 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4605 } else {
4606 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4607 adev->adm_init = (adm_init_t)
4608 dlsym(adev->adm_lib, "adm_init");
4609 adev->adm_deinit = (adm_deinit_t)
4610 dlsym(adev->adm_lib, "adm_deinit");
4611 adev->adm_register_input_stream = (adm_register_input_stream_t)
4612 dlsym(adev->adm_lib, "adm_register_input_stream");
4613 adev->adm_register_output_stream = (adm_register_output_stream_t)
4614 dlsym(adev->adm_lib, "adm_register_output_stream");
4615 adev->adm_deregister_stream = (adm_deregister_stream_t)
4616 dlsym(adev->adm_lib, "adm_deregister_stream");
4617 adev->adm_request_focus = (adm_request_focus_t)
4618 dlsym(adev->adm_lib, "adm_request_focus");
4619 adev->adm_abandon_focus = (adm_abandon_focus_t)
4620 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004621 adev->adm_set_config = (adm_set_config_t)
4622 dlsym(adev->adm_lib, "adm_set_config");
4623 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4624 dlsym(adev->adm_lib, "adm_request_focus_v2");
4625 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4626 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4627 adev->adm_on_routing_change = (adm_on_routing_change_t)
4628 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004629 }
4630 }
4631
Mingming Yin514a8bc2014-07-29 15:22:21 -07004632 adev->bt_wb_speech_enabled = false;
4633
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004634 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 *device = &adev->device.common;
4636
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004637 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4638 &adev->streams_output_cfg_list);
4639
Kiran Kandi910e1862013-10-29 13:29:42 -07004640 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004641
4642 char value[PROPERTY_VALUE_MAX];
4643 int trial;
4644 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4645 trial = atoi(value);
4646 if (period_size_is_plausible_for_low_latency(trial)) {
4647 pcm_config_low_latency.period_size = trial;
4648 pcm_config_low_latency.start_threshold = trial / 4;
4649 pcm_config_low_latency.avail_min = trial / 4;
4650 configured_low_latency_capture_period_size = trial;
4651 }
4652 }
4653 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4654 trial = atoi(value);
4655 if (period_size_is_plausible_for_low_latency(trial)) {
4656 configured_low_latency_capture_period_size = trial;
4657 }
4658 }
4659
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004660 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4661 af_period_multiplier = atoi(value);
4662 if (af_period_multiplier < 0)
4663 af_period_multiplier = 2;
4664 else if (af_period_multiplier > 4)
4665 af_period_multiplier = 4;
4666
4667 ALOGV("new period_multiplier = %d", af_period_multiplier);
4668 }
4669
vivek mehta446c3962015-09-14 10:57:35 -07004670 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004671 pthread_mutex_unlock(&adev_init_lock);
4672
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004673 if (adev->adm_init)
4674 adev->adm_data = adev->adm_init();
4675
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304676 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004677 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 return 0;
4679}
4680
4681static struct hw_module_methods_t hal_module_methods = {
4682 .open = adev_open,
4683};
4684
4685struct audio_module HAL_MODULE_INFO_SYM = {
4686 .common = {
4687 .tag = HARDWARE_MODULE_TAG,
4688 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4689 .hal_api_version = HARDWARE_HAL_API_VERSION,
4690 .id = AUDIO_HARDWARE_MODULE_ID,
4691 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004692 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 .methods = &hal_module_methods,
4694 },
4695};