blob: bce5ceadb6196699b6557bbd6d5fbc7dbf7ce9ae [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) {
2352 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2353 adev->perf_lock_opts,
2354 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002355 if (!same_dev) {
2356 ALOGV("update routing change");
2357 out->routing_change = true;
2358 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002359 select_devices(adev, out->usecase);
2360 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2361 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002362 }
2363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002365 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002367
2368 if (out == adev->primary_output) {
2369 pthread_mutex_lock(&adev->lock);
2370 audio_extn_set_parameters(adev, parms);
2371 pthread_mutex_unlock(&adev->lock);
2372 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002373 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002374 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002375 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002376
2377 audio_extn_dts_create_state_notifier_node(out->usecase);
2378 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2379 popcount(out->channel_mask),
2380 out->playback_started);
2381
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002382 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002383 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302386error:
Eric Laurent994a6932013-07-17 11:51:42 -07002387 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 return ret;
2389}
2390
2391static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2392{
2393 struct stream_out *out = (struct stream_out *)stream;
2394 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002395 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396 char value[256];
2397 struct str_parms *reply = str_parms_create();
2398 size_t i, j;
2399 int ret;
2400 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002401
2402 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002403 if (reply) {
2404 str_parms_destroy(reply);
2405 }
2406 if (query) {
2407 str_parms_destroy(query);
2408 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002409 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2410 return NULL;
2411 }
2412
Eric Laurent994a6932013-07-17 11:51:42 -07002413 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2415 if (ret >= 0) {
2416 value[0] = '\0';
2417 i = 0;
2418 while (out->supported_channel_masks[i] != 0) {
2419 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2420 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2421 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002422 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002424 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 first = false;
2426 break;
2427 }
2428 }
2429 i++;
2430 }
2431 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2432 str = str_parms_to_str(reply);
2433 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002434 voice_extn_out_get_parameters(out, query, reply);
2435 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002436 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002437 free(str);
2438 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002439 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002441
Alexy Joseph62142aa2015-11-16 15:10:34 -08002442
2443 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2444 if (ret >= 0) {
2445 value[0] = '\0';
2446 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2447 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302448 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002449 } else {
2450 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302451 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002452 }
2453 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002454 if (str)
2455 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002456 str = str_parms_to_str(reply);
2457 }
2458
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002459 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2460 if (ret >= 0) {
2461 value[0] = '\0';
2462 i = 0;
2463 first = true;
2464 while (out->supported_formats[i] != 0) {
2465 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2466 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2467 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002468 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002469 }
2470 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2471 first = false;
2472 break;
2473 }
2474 }
2475 i++;
2476 }
2477 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002478 if (str)
2479 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002480 str = str_parms_to_str(reply);
2481 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002482
2483 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2484 if (ret >= 0) {
2485 value[0] = '\0';
2486 i = 0;
2487 first = true;
2488 while (out->supported_sample_rates[i] != 0) {
2489 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2490 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2491 if (!first) {
2492 strlcat(value, "|", sizeof(value));
2493 }
2494 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2495 first = false;
2496 break;
2497 }
2498 }
2499 i++;
2500 }
2501 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2502 if (str)
2503 free(str);
2504 str = str_parms_to_str(reply);
2505 }
2506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 str_parms_destroy(query);
2508 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002509 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 return str;
2511}
2512
2513static uint32_t out_get_latency(const struct audio_stream_out *stream)
2514{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002515 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002517 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518
Alexy Josephaa54c872014-12-03 02:46:47 -08002519 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002520 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002521 } else if (out->realtime) {
2522 // since the buffer won't be filled up faster than realtime,
2523 // return a smaller number
2524 if (out->config.rate)
2525 period_ms = (out->af_period_multiplier * out->config.period_size *
2526 1000) / (out->config.rate);
2527 else
2528 period_ms = 0;
2529 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002530 } else {
2531 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002533 }
2534
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302535 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002536 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537}
2538
2539static int out_set_volume(struct audio_stream_out *stream, float left,
2540 float right)
2541{
Eric Laurenta9024de2013-04-04 09:19:12 -07002542 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002543 int volume[2];
2544
Eric Laurenta9024de2013-04-04 09:19:12 -07002545 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2546 /* only take left channel into account: the API is for stereo anyway */
2547 out->muted = (left == 0.0f);
2548 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002549 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302550 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002551 /*
2552 * Set mute or umute on HDMI passthrough stream.
2553 * Only take left channel into account.
2554 * Mute is 0 and unmute 1
2555 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302556 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002557 } else {
2558 char mixer_ctl_name[128];
2559 struct audio_device *adev = out->dev;
2560 struct mixer_ctl *ctl;
2561 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002562 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002563
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002564 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2565 "Compress Playback %d Volume", pcm_device_id);
2566 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2567 if (!ctl) {
2568 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2569 __func__, mixer_ctl_name);
2570 return -EINVAL;
2571 }
2572 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2573 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2574 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2575 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002577 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002579 return -ENOSYS;
2580}
2581
2582static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2583 size_t bytes)
2584{
2585 struct stream_out *out = (struct stream_out *)stream;
2586 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302587 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002588 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002590 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302591
Naresh Tanniru80659832014-06-04 18:17:56 +05302592 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002593
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302594 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302595 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302596 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2597 pthread_mutex_unlock(&out->lock);
2598 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302599 } else {
2600 /* increase written size during SSR to avoid mismatch
2601 * with the written frames count in AF
2602 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302603 if (audio_bytes_per_sample(out->format) != 0)
2604 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302605 ALOGD(" %s: sound card is not active/SSR state", __func__);
2606 ret= -EIO;
2607 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302608 }
2609 }
2610
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302611 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302612 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2613 if (audio_bytes_per_sample(out->format) != 0)
2614 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2615 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302616 goto exit;
2617 }
2618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002620 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002621 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002622 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2623 ret = voice_extn_compress_voip_start_output_stream(out);
2624 else
2625 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002626 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002629 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 goto exit;
2631 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002632
2633 if (last_known_cal_step != -1) {
2634 ALOGD("%s: retry previous failed cal level set", __func__);
2635 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2636 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638
Ashish Jain81eb2a82015-05-13 10:52:34 +05302639 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002640 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302641 adev->is_channel_status_set = true;
2642 }
2643
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002644 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002645 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002646 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002647 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002648 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2649 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302650 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2651 ALOGD("copl(%p):send next track params in gapless", out);
2652 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2653 out->send_next_track_params = false;
2654 out->is_compr_metadata_avail = false;
2655 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002656 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302657 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302658 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002659
Ashish Jain83a6cc22016-06-28 14:34:17 +05302660 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302661 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302662 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302663 pthread_mutex_unlock(&out->lock);
2664 return -EINVAL;
2665 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302666 audio_format_t dst_format = out->hal_op_format;
2667 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302668
2669 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2670 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2671
Ashish Jain83a6cc22016-06-28 14:34:17 +05302672 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302673 dst_format,
2674 buffer,
2675 src_format,
2676 frames);
2677
Ashish Jain83a6cc22016-06-28 14:34:17 +05302678 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302679 bytes_to_write);
2680
2681 /*Convert written bytes in audio flinger format*/
2682 if (ret > 0)
2683 ret = ((ret * format_to_bitwidth_table[out->format]) /
2684 format_to_bitwidth_table[dst_format]);
2685 }
2686 } else
2687 ret = compress_write(out->compr, buffer, bytes);
2688
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302689 if (ret < 0)
2690 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302691 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002692 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302693 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002694 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302695 } else if (-ENETRESET == ret) {
2696 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2697 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2698 pthread_mutex_unlock(&out->lock);
2699 out_standby(&out->stream.common);
2700 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 }
Ashish Jain5106d362016-05-11 19:23:33 +05302702 if ( ret == (ssize_t)bytes && !out->non_blocking)
2703 out->written += bytes;
2704
Naresh Tanniru80659832014-06-04 18:17:56 +05302705 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002706 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002707 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002708 out->playback_started = 1;
2709 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002710
2711 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2712 popcount(out->channel_mask),
2713 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002714 }
2715 pthread_mutex_unlock(&out->lock);
2716 return ret;
2717 } else {
2718 if (out->pcm) {
2719 if (out->muted)
2720 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002721
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302722 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002723
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002724 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002725
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002726 if (out->config.rate)
2727 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2728 out->config.rate;
2729
2730 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2731
2732 request_out_focus(out, ns);
2733
2734 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002735 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002736 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302737 out->convert_buffer != NULL) {
2738
2739 memcpy_by_audio_format(out->convert_buffer,
2740 out->hal_op_format,
2741 buffer,
2742 out->hal_ip_format,
2743 out->config.period_size * out->config.channels);
2744
2745 ret = pcm_write(out->pcm, out->convert_buffer,
2746 (out->config.period_size *
2747 out->config.channels *
2748 format_to_bitwidth_table[out->hal_op_format]));
2749 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002750 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302751 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002752
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002753 release_out_focus(out);
2754
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302755 if (ret < 0)
2756 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302757 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2758 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2759 else
2760 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 }
2763
2764exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302765 /* ToDo: There may be a corner case when SSR happens back to back during
2766 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302767 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302768 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302769 }
2770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771 pthread_mutex_unlock(&out->lock);
2772
2773 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002774 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002775 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302776 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302777 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302778 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302779 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302780 out->standby = true;
2781 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302783 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302784 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785 }
2786 return bytes;
2787}
2788
2789static int out_get_render_position(const struct audio_stream_out *stream,
2790 uint32_t *dsp_frames)
2791{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002792 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302793 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002794
2795 if (dsp_frames == NULL)
2796 return -EINVAL;
2797
2798 *dsp_frames = 0;
2799 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002800 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302801
2802 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2803 * this operation and adev_close_output_stream(where out gets reset).
2804 */
2805 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2806 *dsp_frames = get_actual_pcm_frames_rendered(out);
2807 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2808 return 0;
2809 }
2810
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002811 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302812 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302813 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302815 if (ret < 0)
2816 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302818 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002819 }
2820 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302821 if (-ENETRESET == ret) {
2822 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2823 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2824 return -EINVAL;
2825 } else if(ret < 0) {
2826 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2827 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302828 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2829 /*
2830 * Handle corner case where compress session is closed during SSR
2831 * and timestamp is queried
2832 */
2833 ALOGE(" ERROR: sound card not active, return error");
2834 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302835 } else {
2836 return 0;
2837 }
Zhou Song32a556e2015-05-05 10:46:56 +08002838 } else if (audio_is_linear_pcm(out->format)) {
2839 *dsp_frames = out->written;
2840 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002841 } else
2842 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843}
2844
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002845static int out_add_audio_effect(const struct audio_stream *stream __unused,
2846 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847{
2848 return 0;
2849}
2850
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002851static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2852 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853{
2854 return 0;
2855}
2856
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002857static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2858 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859{
2860 return -EINVAL;
2861}
2862
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002863static int out_get_presentation_position(const struct audio_stream_out *stream,
2864 uint64_t *frames, struct timespec *timestamp)
2865{
2866 struct stream_out *out = (struct stream_out *)stream;
2867 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002868 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002869
Ashish Jain5106d362016-05-11 19:23:33 +05302870 /* below piece of code is not guarded against any lock because audioFliner serializes
2871 * this operation and adev_close_output_stream( where out gets reset).
2872 */
2873 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2874 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2875 *frames = get_actual_pcm_frames_rendered(out);
2876 /* this is the best we can do */
2877 clock_gettime(CLOCK_MONOTONIC, timestamp);
2878 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2879 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2880 return 0;
2881 }
2882
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002883 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002884
Ashish Jain5106d362016-05-11 19:23:33 +05302885 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2886 ret = compress_get_tstamp(out->compr, &dsp_frames,
2887 &out->sample_rate);
2888 ALOGVV("%s rendered frames %ld sample_rate %d",
2889 __func__, dsp_frames, out->sample_rate);
2890 *frames = dsp_frames;
2891 if (ret < 0)
2892 ret = -errno;
2893 if (-ENETRESET == ret) {
2894 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2895 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2896 ret = -EINVAL;
2897 } else
2898 ret = 0;
2899 /* this is the best we can do */
2900 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002901 } else {
2902 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002903 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002904 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2905 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002906 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002907 // This adjustment accounts for buffering after app processor.
2908 // It is based on estimated DSP latency per use case, rather than exact.
2909 signed_frames -=
2910 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2911
Eric Laurent949a0892013-09-20 09:20:13 -07002912 // It would be unusual for this value to be negative, but check just in case ...
2913 if (signed_frames >= 0) {
2914 *frames = signed_frames;
2915 ret = 0;
2916 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002917 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302918 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2919 *frames = out->written;
2920 clock_gettime(CLOCK_MONOTONIC, timestamp);
2921 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002922 }
2923 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002924 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002925 return ret;
2926}
2927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928static int out_set_callback(struct audio_stream_out *stream,
2929 stream_callback_t callback, void *cookie)
2930{
2931 struct stream_out *out = (struct stream_out *)stream;
2932
2933 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002934 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002935 out->offload_callback = callback;
2936 out->offload_cookie = cookie;
2937 pthread_mutex_unlock(&out->lock);
2938 return 0;
2939}
2940
2941static int out_pause(struct audio_stream_out* stream)
2942{
2943 struct stream_out *out = (struct stream_out *)stream;
2944 int status = -ENOSYS;
2945 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002946 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002947 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002948 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302950 struct audio_device *adev = out->dev;
2951 int snd_scard_state = get_snd_card_state(adev);
2952
2953 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2954 status = compress_pause(out->compr);
2955
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002957
Mingming Yin21854652016-04-13 11:54:02 -07002958 if (audio_extn_passthru_is_active()) {
2959 ALOGV("offload use case, pause passthru");
2960 audio_extn_passthru_on_pause(out);
2961 }
2962
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302963 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002964 audio_extn_dts_notify_playback_state(out->usecase, 0,
2965 out->sample_rate, popcount(out->channel_mask),
2966 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002967 }
2968 pthread_mutex_unlock(&out->lock);
2969 }
2970 return status;
2971}
2972
2973static int out_resume(struct audio_stream_out* stream)
2974{
2975 struct stream_out *out = (struct stream_out *)stream;
2976 int status = -ENOSYS;
2977 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002978 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002979 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002980 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002981 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002982 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302983 struct audio_device *adev = out->dev;
2984 int snd_scard_state = get_snd_card_state(adev);
2985
Mingming Yin21854652016-04-13 11:54:02 -07002986 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2987 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2988 pthread_mutex_lock(&out->dev->lock);
2989 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07002990 pthread_mutex_unlock(&out->dev->lock);
2991 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302992 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002993 }
2994 if (!status) {
2995 out->offload_state = OFFLOAD_STATE_PLAYING;
2996 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302997 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002998 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2999 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 }
3001 pthread_mutex_unlock(&out->lock);
3002 }
3003 return status;
3004}
3005
3006static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3007{
3008 struct stream_out *out = (struct stream_out *)stream;
3009 int status = -ENOSYS;
3010 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003011 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003012 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003013 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3014 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3015 else
3016 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3017 pthread_mutex_unlock(&out->lock);
3018 }
3019 return status;
3020}
3021
3022static int out_flush(struct audio_stream_out* stream)
3023{
3024 struct stream_out *out = (struct stream_out *)stream;
3025 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003026 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003027 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003028 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003029 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303030 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003031 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003032 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 return 0;
3034 }
3035 return -ENOSYS;
3036}
3037
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038/** audio_stream_in implementation **/
3039static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3040{
3041 struct stream_in *in = (struct stream_in *)stream;
3042
3043 return in->config.rate;
3044}
3045
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003046static int in_set_sample_rate(struct audio_stream *stream __unused,
3047 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048{
3049 return -ENOSYS;
3050}
3051
3052static size_t in_get_buffer_size(const struct audio_stream *stream)
3053{
3054 struct stream_in *in = (struct stream_in *)stream;
3055
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003056 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3057 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003058 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3059 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003060
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003061 return in->config.period_size * in->af_period_multiplier *
3062 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063}
3064
3065static uint32_t in_get_channels(const struct audio_stream *stream)
3066{
3067 struct stream_in *in = (struct stream_in *)stream;
3068
3069 return in->channel_mask;
3070}
3071
3072static audio_format_t in_get_format(const struct audio_stream *stream)
3073{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003074 struct stream_in *in = (struct stream_in *)stream;
3075
3076 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077}
3078
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003079static int in_set_format(struct audio_stream *stream __unused,
3080 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081{
3082 return -ENOSYS;
3083}
3084
3085static int in_standby(struct audio_stream *stream)
3086{
3087 struct stream_in *in = (struct stream_in *)stream;
3088 struct audio_device *adev = in->dev;
3089 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303090 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3091 stream, in->usecase, use_case_table[in->usecase]);
3092
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003093 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003094 if (!in->standby && in->is_st_session) {
3095 ALOGD("%s: sound trigger pcm stop lab", __func__);
3096 audio_extn_sound_trigger_stop_lab(in);
3097 in->standby = 1;
3098 }
3099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003101 if (adev->adm_deregister_stream)
3102 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3103
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003104 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003106 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3107 voice_extn_compress_voip_close_input_stream(stream);
3108 ALOGD("VOIP input entered standby");
3109 } else {
3110 if (in->pcm) {
3111 pcm_close(in->pcm);
3112 in->pcm = NULL;
3113 }
3114 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003115 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003116 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 }
3118 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003119 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 return status;
3121}
3122
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003123static int in_dump(const struct audio_stream *stream __unused,
3124 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125{
3126 return 0;
3127}
3128
3129static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3130{
3131 struct stream_in *in = (struct stream_in *)stream;
3132 struct audio_device *adev = in->dev;
3133 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003135 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303137 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 parms = str_parms_create_str(kvpairs);
3139
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303140 if (!parms)
3141 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003142 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003143 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003144
3145 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3146 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 val = atoi(value);
3148 /* no audio source uses val == 0 */
3149 if ((in->source != val) && (val != 0)) {
3150 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003151 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3152 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3153 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003154 (in->config.rate == 8000 || in->config.rate == 16000 ||
3155 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003156 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003157 err = voice_extn_compress_voip_open_input_stream(in);
3158 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003159 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003160 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003161 }
3162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 }
3164 }
3165
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003166 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3167 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003169 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170 in->device = val;
3171 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003172 if (!in->standby && !in->is_st_session) {
3173 ALOGV("update input routing change");
3174 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003175 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003176 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 }
3178 }
3179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003181 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003182
3183 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303184error:
Eric Laurent994a6932013-07-17 11:51:42 -07003185 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 return ret;
3187}
3188
3189static char* in_get_parameters(const struct audio_stream *stream,
3190 const char *keys)
3191{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003192 struct stream_in *in = (struct stream_in *)stream;
3193 struct str_parms *query = str_parms_create_str(keys);
3194 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003195 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003196
3197 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003198 if (reply) {
3199 str_parms_destroy(reply);
3200 }
3201 if (query) {
3202 str_parms_destroy(query);
3203 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003204 ALOGE("in_get_parameters: failed to create query or reply");
3205 return NULL;
3206 }
3207
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003208 ALOGV("%s: enter: keys - %s", __func__, keys);
3209
3210 voice_extn_in_get_parameters(in, query, reply);
3211
3212 str = str_parms_to_str(reply);
3213 str_parms_destroy(query);
3214 str_parms_destroy(reply);
3215
3216 ALOGV("%s: exit: returns - %s", __func__, str);
3217 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218}
3219
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003220static int in_set_gain(struct audio_stream_in *stream __unused,
3221 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222{
3223 return 0;
3224}
3225
3226static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3227 size_t bytes)
3228{
3229 struct stream_in *in = (struct stream_in *)stream;
3230 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303231 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303232 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303233 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003235 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303236
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003237 if (in->is_st_session) {
3238 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3239 /* Read from sound trigger HAL */
3240 audio_extn_sound_trigger_read(in, buffer, bytes);
3241 pthread_mutex_unlock(&in->lock);
3242 return bytes;
3243 }
3244
Ashish Jainbbce4322016-02-16 13:25:27 +05303245 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003246 ALOGD(" %s: sound card is not active/SSR state", __func__);
3247 ret= -EIO;;
3248 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303249 }
3250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003252 pthread_mutex_lock(&adev->lock);
3253 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3254 ret = voice_extn_compress_voip_start_input_stream(in);
3255 else
3256 ret = start_input_stream(in);
3257 pthread_mutex_unlock(&adev->lock);
3258 if (ret != 0) {
3259 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 }
3261 in->standby = 0;
3262 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003264 // what's the duration requested by the client?
3265 long ns = 0;
3266
3267 if (in->config.rate)
3268 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3269 in->config.rate;
3270
3271 request_in_focus(in, ns);
3272 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303275 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003276 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303277 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003278 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003279 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003280 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303281 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003282 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303283 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3284 if (bytes % 4 == 0) {
3285 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3286 int_buf_stream = buffer;
3287 for (size_t itt=0; itt < bytes/4 ; itt++) {
3288 int_buf_stream[itt] >>= 8;
3289 }
3290 } else {
3291 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3292 ret = -EINVAL;
3293 goto exit;
3294 }
3295 } if (ret < 0) {
3296 ret = -errno;
3297 }
3298 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003299 }
3300
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003301 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 /*
3304 * Instead of writing zeroes here, we could trust the hardware
3305 * to always provide zeroes when muted.
3306 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303307 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3308 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 memset(buffer, 0, bytes);
3310
3311exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303312 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303313 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003314 if (-ENETRESET == ret)
3315 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 pthread_mutex_unlock(&in->lock);
3318
3319 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303320 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303321 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303322 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303323 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303324 in->standby = true;
3325 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303326 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003328 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303329 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303330 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 }
3332 return bytes;
3333}
3334
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003335static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336{
3337 return 0;
3338}
3339
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003340static int add_remove_audio_effect(const struct audio_stream *stream,
3341 effect_handle_t effect,
3342 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003344 struct stream_in *in = (struct stream_in *)stream;
3345 int status = 0;
3346 effect_descriptor_t desc;
3347
3348 status = (*effect)->get_descriptor(effect, &desc);
3349 if (status != 0)
3350 return status;
3351
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003352 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003353 pthread_mutex_lock(&in->dev->lock);
3354 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3355 in->enable_aec != enable &&
3356 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3357 in->enable_aec = enable;
3358 if (!in->standby)
3359 select_devices(in->dev, in->usecase);
3360 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003361 if (in->enable_ns != enable &&
3362 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3363 in->enable_ns = enable;
3364 if (!in->standby)
3365 select_devices(in->dev, in->usecase);
3366 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003367 pthread_mutex_unlock(&in->dev->lock);
3368 pthread_mutex_unlock(&in->lock);
3369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 return 0;
3371}
3372
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003373static int in_add_audio_effect(const struct audio_stream *stream,
3374 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375{
Eric Laurent994a6932013-07-17 11:51:42 -07003376 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003377 return add_remove_audio_effect(stream, effect, true);
3378}
3379
3380static int in_remove_audio_effect(const struct audio_stream *stream,
3381 effect_handle_t effect)
3382{
Eric Laurent994a6932013-07-17 11:51:42 -07003383 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003384 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385}
3386
3387static int adev_open_output_stream(struct audio_hw_device *dev,
3388 audio_io_handle_t handle,
3389 audio_devices_t devices,
3390 audio_output_flags_t flags,
3391 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003392 struct audio_stream_out **stream_out,
3393 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394{
3395 struct audio_device *adev = (struct audio_device *)dev;
3396 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303397 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003398 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003400 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303401
3402 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3403 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003404 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303405 return -EINVAL;
3406 }
3407
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003408 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3409
Mingming Yin3a941d42016-02-17 18:08:05 -08003410 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3411 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303412 devices, flags, &out->stream);
3413
3414
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003415 if (!out) {
3416 return -ENOMEM;
3417 }
3418
Haynes Mathew George204045b2015-02-25 20:32:03 -08003419 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003420 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003421 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 if (devices == AUDIO_DEVICE_NONE)
3424 devices = AUDIO_DEVICE_OUT_SPEAKER;
3425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426 out->flags = flags;
3427 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003428 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003429 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 out->sample_rate = config->sample_rate;
3431 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3432 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003433 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003434 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003435 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303436 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437
Mingming Yin3a941d42016-02-17 18:08:05 -08003438 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3439 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3440 pthread_mutex_lock(&adev->lock);
3441 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3442 ret = read_hdmi_sink_caps(out);
3443 pthread_mutex_unlock(&adev->lock);
3444 if (ret != 0) {
3445 if (ret == -ENOSYS) {
3446 /* ignore and go with default */
3447 ret = 0;
3448 } else {
3449 ALOGE("error reading hdmi sink caps");
3450 goto error_open;
3451 }
3452 }
3453 }
3454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003455 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003456 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303457 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3458 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003459 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3460 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3461
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003462 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003463 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3464 /*
3465 * Do not handle stereo output in Multi-channel cases
3466 * Stereo case is handled in normal playback path
3467 */
3468 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3469 ret = AUDIO_CHANNEL_OUT_STEREO;
3470 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003471
3472 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3473 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003474 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003475 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003476 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003477
3478 if (config->sample_rate == 0)
3479 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3480 if (config->channel_mask == 0)
3481 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003482 if (config->format == 0)
3483 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003484
3485 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003487 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3489 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003491 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003493 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3494 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003495 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003496 ret = voice_extn_compress_voip_open_output_stream(out);
3497 if (ret != 0) {
3498 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3499 __func__, ret);
3500 goto error_open;
3501 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003502 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3503 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3504
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3506 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3507 ALOGE("%s: Unsupported Offload information", __func__);
3508 ret = -EINVAL;
3509 goto error_open;
3510 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003511
Mingming Yin3a941d42016-02-17 18:08:05 -08003512 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003513 if(config->offload_info.format == 0)
3514 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003515 if (config->offload_info.sample_rate == 0)
3516 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003517 }
3518
Mingming Yin90310102013-11-13 16:57:00 -08003519 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303520 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003521 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 ret = -EINVAL;
3523 goto error_open;
3524 }
3525
3526 out->compr_config.codec = (struct snd_codec *)
3527 calloc(1, sizeof(struct snd_codec));
3528
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003529 if (!out->compr_config.codec) {
3530 ret = -ENOMEM;
3531 goto error_open;
3532 }
3533
vivek mehta0ea887a2015-08-26 14:01:20 -07003534 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303535 out->stream.pause = out_pause;
3536 out->stream.flush = out_flush;
3537 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003538 out->usecase = get_offload_usecase(adev, true);
3539 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003540 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003541 out->stream.set_callback = out_set_callback;
3542 out->stream.pause = out_pause;
3543 out->stream.resume = out_resume;
3544 out->stream.drain = out_drain;
3545 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003546 out->usecase = get_offload_usecase(adev, false);
3547 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003548 }
vivek mehta446c3962015-09-14 10:57:35 -07003549
3550 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003551 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3552 config->format == 0 && config->sample_rate == 0 &&
3553 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003554 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003555 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3556 } else {
3557 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3558 ret = -EEXIST;
3559 goto error_open;
3560 }
vivek mehta446c3962015-09-14 10:57:35 -07003561 }
3562
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 if (config->offload_info.channel_mask)
3564 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003565 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003566 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003567 config->offload_info.channel_mask = config->channel_mask;
3568 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003569 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003570 out->sample_rate = config->offload_info.sample_rate;
3571
Mingming Yin3ee55c62014-08-04 14:23:35 -07003572 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003573
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303574 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3575 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3576 audio_extn_dolby_send_ddp_endp_params(adev);
3577 audio_extn_dolby_set_dmid(adev);
3578 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003579
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003580 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003581 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 out->compr_config.codec->bit_rate =
3583 config->offload_info.bit_rate;
3584 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303585 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003586 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303587 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003588 /*TODO: Do we need to change it for passthrough */
3589 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003590
Manish Dewangana6fc5442015-08-24 20:30:31 +05303591 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3592 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3593 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3594 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303595
3596 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3597 AUDIO_FORMAT_PCM) {
3598
3599 /*Based on platform support, configure appropriate alsa format for corresponding
3600 *hal input format.
3601 */
3602 out->compr_config.codec->format = hal_format_to_alsa(
3603 config->offload_info.format);
3604
Ashish Jain83a6cc22016-06-28 14:34:17 +05303605 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303606 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303607 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303608
3609 /*for direct PCM playback populate bit_width based on selected alsa format as
3610 *hal input format and alsa format might differ based on platform support.
3611 */
3612 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303613 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303614
3615 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3616
3617 /* Check if alsa session is configured with the same format as HAL input format,
3618 * if not then derive correct fragment size needed to accomodate the
3619 * conversion of HAL input format to alsa format.
3620 */
3621 audio_extn_utils_update_direct_pcm_fragment_size(out);
3622
3623 /*if hal input and output fragment size is different this indicates HAL input format is
3624 *not same as the alsa format
3625 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303626 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303627 /*Allocate a buffer to convert input data to the alsa configured format.
3628 *size of convert buffer is equal to the size required to hold one fragment size
3629 *worth of pcm data, this is because flinger does not write more than fragment_size
3630 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303631 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3632 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303633 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3634 ret = -ENOMEM;
3635 goto error_open;
3636 }
3637 }
3638 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3639 out->compr_config.fragment_size =
3640 audio_extn_passthru_get_buffer_size(&config->offload_info);
3641 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3642 } else {
3643 out->compr_config.fragment_size =
3644 platform_get_compress_offload_buffer_size(&config->offload_info);
3645 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3646 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003647
Amit Shekhar6f461b12014-08-01 14:52:58 -07003648 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303649 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003650
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003651 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3652 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003653
Alexy Josephaa54c872014-12-03 02:46:47 -08003654
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003655 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303656 out->send_next_track_params = false;
3657 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003658 out->offload_state = OFFLOAD_STATE_IDLE;
3659 out->playback_started = 0;
3660
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003661 audio_extn_dts_create_state_notifier_node(out->usecase);
3662
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 create_offload_callback_thread(out);
3664 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3665 __func__, config->offload_info.version,
3666 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303667
3668 /* Disable gapless if any of the following is true
3669 * passthrough playback
3670 * AV playback
3671 * Direct PCM playback
3672 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303673 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303674 config->offload_info.has_video ||
3675 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3676 check_and_set_gapless_mode(adev, false);
3677 } else
3678 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003679
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303680 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003681 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3682 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003683 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303684 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003685 if (ret != 0) {
3686 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3687 __func__, ret);
3688 goto error_open;
3689 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003690 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3691 if (config->sample_rate == 0)
3692 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3693 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3694 config->sample_rate != 8000) {
3695 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3696 ret = -EINVAL;
3697 goto error_open;
3698 }
3699 out->sample_rate = config->sample_rate;
3700 out->config.rate = config->sample_rate;
3701 if (config->format == AUDIO_FORMAT_DEFAULT)
3702 config->format = AUDIO_FORMAT_PCM_16_BIT;
3703 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3704 config->format = AUDIO_FORMAT_PCM_16_BIT;
3705 ret = -EINVAL;
3706 goto error_open;
3707 }
3708 out->format = config->format;
3709 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3710 out->config = pcm_config_afe_proxy_playback;
3711 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003712 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303713 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3714 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003715 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3716 out->flags);
3717 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303718 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3719 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3720 out->config = pcm_config_low_latency;
3721 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3722 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3723 out->config = pcm_config_deep_buffer;
3724 } else {
3725 /* primary path is the default path selected if no other outputs are available/suitable */
3726 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3727 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3728 }
3729 out->hal_ip_format = format = out->format;
3730 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3731 out->hal_op_format = pcm_format_to_hal(out->config.format);
3732 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3733 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003734 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303735 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3736 if (out->hal_ip_format != out->hal_op_format) {
3737 uint32_t buffer_size = out->config.period_size *
3738 format_to_bitwidth_table[out->hal_op_format] *
3739 out->config.channels;
3740 out->convert_buffer = calloc(1, buffer_size);
3741 if (out->convert_buffer == NULL){
3742 ALOGE("Allocation failed for convert buffer for size %d",
3743 out->compr_config.fragment_size);
3744 ret = -ENOMEM;
3745 goto error_open;
3746 }
3747 ALOGD("Convert buffer allocated of size %d", buffer_size);
3748 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 }
3750
Ashish Jain83a6cc22016-06-28 14:34:17 +05303751 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3752 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3753
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003754 /* TODO remove this hardcoding and check why width is zero*/
3755 if (out->bit_width == 0)
3756 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003757 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3758 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003759 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303760 out->bit_width, out->channel_mask,
3761 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003762 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3763 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3764 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003765 if(adev->primary_output == NULL)
3766 adev->primary_output = out;
3767 else {
3768 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003769 ret = -EEXIST;
3770 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003771 }
3772 }
3773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 /* Check if this usecase is already existing */
3775 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003776 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3777 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003780 ret = -EEXIST;
3781 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 }
3783 pthread_mutex_unlock(&adev->lock);
3784
3785 out->stream.common.get_sample_rate = out_get_sample_rate;
3786 out->stream.common.set_sample_rate = out_set_sample_rate;
3787 out->stream.common.get_buffer_size = out_get_buffer_size;
3788 out->stream.common.get_channels = out_get_channels;
3789 out->stream.common.get_format = out_get_format;
3790 out->stream.common.set_format = out_set_format;
3791 out->stream.common.standby = out_standby;
3792 out->stream.common.dump = out_dump;
3793 out->stream.common.set_parameters = out_set_parameters;
3794 out->stream.common.get_parameters = out_get_parameters;
3795 out->stream.common.add_audio_effect = out_add_audio_effect;
3796 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3797 out->stream.get_latency = out_get_latency;
3798 out->stream.set_volume = out_set_volume;
3799 out->stream.write = out_write;
3800 out->stream.get_render_position = out_get_render_position;
3801 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003802 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003804 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003806 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003807 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808
3809 config->format = out->stream.common.get_format(&out->stream.common);
3810 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3811 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3812
3813 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303814 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003815 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003816
3817 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3818 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3819 popcount(out->channel_mask), out->playback_started);
3820
Eric Laurent994a6932013-07-17 11:51:42 -07003821 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003823
3824error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303825 if (out->convert_buffer)
3826 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003827 free(out);
3828 *stream_out = NULL;
3829 ALOGD("%s: exit: ret %d", __func__, ret);
3830 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831}
3832
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003833static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 struct audio_stream_out *stream)
3835{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836 struct stream_out *out = (struct stream_out *)stream;
3837 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003838 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003839
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303840 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3841
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003842 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303843 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003844 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303845 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003846 if(ret != 0)
3847 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3848 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003849 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003850 out_standby(&stream->common);
3851
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003852 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003853 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003854 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003855 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003856 if (out->compr_config.codec != NULL)
3857 free(out->compr_config.codec);
3858 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003859
Ashish Jain83a6cc22016-06-28 14:34:17 +05303860 if (out->convert_buffer != NULL) {
3861 free(out->convert_buffer);
3862 out->convert_buffer = NULL;
3863 }
3864
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003865 if (adev->voice_tx_output == out)
3866 adev->voice_tx_output = NULL;
3867
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003868 pthread_cond_destroy(&out->cond);
3869 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003871 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872}
3873
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003874static void close_compress_sessions(struct audio_device *adev)
3875{
Mingming Yin7b762e72015-03-04 13:47:32 -08003876 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303877 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003878 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003879 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303880
3881 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003882 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303883 if (is_offload_usecase(usecase->id)) {
3884 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003885 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3886 out = usecase->stream.out;
3887 pthread_mutex_unlock(&adev->lock);
3888 out_standby(&out->stream.common);
3889 pthread_mutex_lock(&adev->lock);
3890 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303891 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003892 }
3893 pthread_mutex_unlock(&adev->lock);
3894}
3895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3897{
3898 struct audio_device *adev = (struct audio_device *)dev;
3899 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003901 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003902 int ret;
3903 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003905 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303908 if (!parms)
3909 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003910 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3911 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303912 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303913 if (strstr(snd_card_status, "OFFLINE")) {
3914 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303915 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003916 //close compress sessions on OFFLINE status
3917 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303918 } else if (strstr(snd_card_status, "ONLINE")) {
3919 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303920 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003921 //send dts hpx license if enabled
3922 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303923 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303924 }
3925
3926 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003927 status = voice_set_parameters(adev, parms);
3928 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003929 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003931 status = platform_set_parameters(adev->platform, parms);
3932 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003933 goto done;
3934
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003935 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3936 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003937 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3939 adev->bluetooth_nrec = true;
3940 else
3941 adev->bluetooth_nrec = false;
3942 }
3943
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003944 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3945 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3947 adev->screen_off = false;
3948 else
3949 adev->screen_off = true;
3950 }
3951
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003952 ret = str_parms_get_int(parms, "rotation", &val);
3953 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003954 bool reverse_speakers = false;
3955 switch(val) {
3956 // FIXME: note that the code below assumes that the speakers are in the correct placement
3957 // relative to the user when the device is rotated 90deg from its default rotation. This
3958 // assumption is device-specific, not platform-specific like this code.
3959 case 270:
3960 reverse_speakers = true;
3961 break;
3962 case 0:
3963 case 90:
3964 case 180:
3965 break;
3966 default:
3967 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003968 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003969 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003970 if (status == 0) {
3971 if (adev->speaker_lr_swap != reverse_speakers) {
3972 adev->speaker_lr_swap = reverse_speakers;
3973 // only update the selected device if there is active pcm playback
3974 struct audio_usecase *usecase;
3975 struct listnode *node;
3976 list_for_each(node, &adev->usecase_list) {
3977 usecase = node_to_item(node, struct audio_usecase, list);
3978 if (usecase->type == PCM_PLAYBACK) {
3979 select_devices(adev, usecase->id);
3980 break;
3981 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003982 }
3983 }
3984 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003985 }
3986
Mingming Yin514a8bc2014-07-29 15:22:21 -07003987 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3988 if (ret >= 0) {
3989 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3990 adev->bt_wb_speech_enabled = true;
3991 else
3992 adev->bt_wb_speech_enabled = false;
3993 }
3994
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003995 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3996 if (ret >= 0) {
3997 val = atoi(value);
3998 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3999 ALOGV("cache new edid");
4000 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004001 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4002 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004003 /*
4004 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4005 * Per AudioPolicyManager, USB device is higher priority than WFD.
4006 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4007 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4008 * starting voice call on USB
4009 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004010 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4011 if (ret >= 0) {
4012 audio_extn_usb_add_device(val, atoi(value));
4013 }
vivek mehta344576a2016-04-12 18:56:03 -07004014 ALOGV("detected USB connect .. disable proxy");
4015 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004016 }
4017 }
4018
4019 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4020 if (ret >= 0) {
4021 val = atoi(value);
4022 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4023 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004024 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004025 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4026 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4027 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4028 if (ret >= 0) {
4029 audio_extn_usb_remove_device(val, atoi(value));
4030 }
vivek mehta344576a2016-04-12 18:56:03 -07004031 ALOGV("detected USB disconnect .. enable proxy");
4032 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004033 }
4034 }
4035
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004036 audio_extn_set_parameters(adev, parms);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304037 // reconfigure should be done only after updating a2dpstate in audio extn
4038 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4039 if (ret >= 0) {
4040 struct audio_usecase *usecase;
4041 struct listnode *node;
4042 list_for_each(node, &adev->usecase_list) {
4043 usecase = node_to_item(node, struct audio_usecase, list);
4044 if ((usecase->type == PCM_PLAYBACK) &&
4045 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4046 ALOGD("reconfigure a2dp... forcing device switch");
4047 //force device switch to re configure encoder
4048 select_devices(adev, usecase->id);
4049 break;
4050 }
4051 }
4052 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004053
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004054done:
4055 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004056 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304057error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004058 ALOGV("%s: exit with code(%d)", __func__, status);
4059 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060}
4061
4062static char* adev_get_parameters(const struct audio_hw_device *dev,
4063 const char *keys)
4064{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004065 struct audio_device *adev = (struct audio_device *)dev;
4066 struct str_parms *reply = str_parms_create();
4067 struct str_parms *query = str_parms_create_str(keys);
4068 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304069 char value[256] = {0};
4070 int ret = 0;
4071
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004072 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004073 if (reply) {
4074 str_parms_destroy(reply);
4075 }
4076 if (query) {
4077 str_parms_destroy(query);
4078 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004079 ALOGE("adev_get_parameters: failed to create query or reply");
4080 return NULL;
4081 }
4082
Naresh Tannirud7205b62014-06-20 02:54:48 +05304083 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4084 sizeof(value));
4085 if (ret >=0) {
4086 int val = 1;
4087 pthread_mutex_lock(&adev->snd_card_status.lock);
4088 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4089 val = 0;
4090 pthread_mutex_unlock(&adev->snd_card_status.lock);
4091 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4092 goto exit;
4093 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004094
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004095 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004096 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004097 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004098 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304099 pthread_mutex_unlock(&adev->lock);
4100
Naresh Tannirud7205b62014-06-20 02:54:48 +05304101exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004102 str = str_parms_to_str(reply);
4103 str_parms_destroy(query);
4104 str_parms_destroy(reply);
4105
4106 ALOGV("%s: exit: returns - %s", __func__, str);
4107 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108}
4109
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004110static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111{
4112 return 0;
4113}
4114
4115static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4116{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004117 int ret;
4118 struct audio_device *adev = (struct audio_device *)dev;
4119 pthread_mutex_lock(&adev->lock);
4120 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004121 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004122 pthread_mutex_unlock(&adev->lock);
4123 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124}
4125
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004126static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4127 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128{
4129 return -ENOSYS;
4130}
4131
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004132static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4133 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004134{
4135 return -ENOSYS;
4136}
4137
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004138static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4139 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140{
4141 return -ENOSYS;
4142}
4143
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004144static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4145 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146{
4147 return -ENOSYS;
4148}
4149
4150static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4151{
4152 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154 pthread_mutex_lock(&adev->lock);
4155 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004156 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004158 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004159 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004160 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004161 adev->current_call_output = NULL;
4162 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 }
4164 pthread_mutex_unlock(&adev->lock);
4165 return 0;
4166}
4167
4168static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4169{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004170 int ret;
4171
4172 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004173 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004174 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4175 pthread_mutex_unlock(&adev->lock);
4176
4177 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178}
4179
4180static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4181{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004182 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 return 0;
4184}
4185
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004186static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187 const struct audio_config *config)
4188{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004189 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004191 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4192 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193}
4194
4195static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004196 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 audio_devices_t devices,
4198 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004199 struct audio_stream_in **stream_in,
4200 audio_input_flags_t flags __unused,
4201 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004202 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004203{
4204 struct audio_device *adev = (struct audio_device *)dev;
4205 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004206 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004207 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004208 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304211 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4212 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215
4216 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004217
4218 if (!in) {
4219 ALOGE("failed to allocate input stream");
4220 return -ENOMEM;
4221 }
4222
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304223 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304224 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4225 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004226 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004227 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 in->stream.common.get_sample_rate = in_get_sample_rate;
4230 in->stream.common.set_sample_rate = in_set_sample_rate;
4231 in->stream.common.get_buffer_size = in_get_buffer_size;
4232 in->stream.common.get_channels = in_get_channels;
4233 in->stream.common.get_format = in_get_format;
4234 in->stream.common.set_format = in_set_format;
4235 in->stream.common.standby = in_standby;
4236 in->stream.common.dump = in_dump;
4237 in->stream.common.set_parameters = in_set_parameters;
4238 in->stream.common.get_parameters = in_get_parameters;
4239 in->stream.common.add_audio_effect = in_add_audio_effect;
4240 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4241 in->stream.set_gain = in_set_gain;
4242 in->stream.read = in_read;
4243 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4244
4245 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004246 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 in->standby = 1;
4249 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004250 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004251 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004252
4253 /* Update config params with the requested sample rate and channels */
4254 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004255 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4256 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4257 is_low_latency = true;
4258#if LOW_LATENCY_CAPTURE_USE_CASE
4259 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4260#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004261 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004262 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004263
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004264 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004265 if (in->realtime) {
4266 in->config = pcm_config_audio_capture_rt;
4267 in->sample_rate = in->config.rate;
4268 in->af_period_multiplier = af_period_multiplier;
4269 } else {
4270 in->config = pcm_config_audio_capture;
4271 in->config.rate = config->sample_rate;
4272 in->sample_rate = config->sample_rate;
4273 in->af_period_multiplier = 1;
4274 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304275 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004277 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304278 if (adev->mode != AUDIO_MODE_IN_CALL) {
4279 ret = -EINVAL;
4280 goto err_open;
4281 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004282 if (config->sample_rate == 0)
4283 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4284 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4285 config->sample_rate != 8000) {
4286 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4287 ret = -EINVAL;
4288 goto err_open;
4289 }
4290 if (config->format == AUDIO_FORMAT_DEFAULT)
4291 config->format = AUDIO_FORMAT_PCM_16_BIT;
4292 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4293 config->format = AUDIO_FORMAT_PCM_16_BIT;
4294 ret = -EINVAL;
4295 goto err_open;
4296 }
4297
4298 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4299 in->config = pcm_config_afe_proxy_record;
4300 in->config.channels = channel_count;
4301 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304302 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304303 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4304 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004305 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004306 audio_extn_compr_cap_format_supported(config->format) &&
4307 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004308 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004309 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304310 /* restrict 24 bit capture for unprocessed source only
4311 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4312 */
4313 if (config->format == AUDIO_FORMAT_DEFAULT) {
4314 config->format = AUDIO_FORMAT_PCM_16_BIT;
4315 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4316 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4317 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4318 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4319 bool ret_error = false;
4320 in->bit_width = 24;
4321 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4322 from HAL is 24_packed and 8_24
4323 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4324 24_packed return error indicating supported format is 24_packed
4325 *> In case of any other source requesting 24 bit or float return error
4326 indicating format supported is 16 bit only.
4327
4328 on error flinger will retry with supported format passed
4329 */
4330 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4331 (source != AUDIO_SOURCE_CAMCORDER)) {
4332 config->format = AUDIO_FORMAT_PCM_16_BIT;
4333 if( config->sample_rate > 48000)
4334 config->sample_rate = 48000;
4335 ret_error = true;
4336 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4337 in->config.format = PCM_FORMAT_S24_3LE;
4338 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4339 in->config.format = PCM_FORMAT_S24_LE;
4340 } else {
4341 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4342 ret_error = true;
4343 }
4344
4345 if (ret_error) {
4346 ret = -EINVAL;
4347 goto err_open;
4348 }
4349 }
4350
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004351 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004352 if (!in->realtime) {
4353 in->format = config->format;
4354 frame_size = audio_stream_in_frame_size(&in->stream);
4355 buffer_size = get_input_buffer_size(config->sample_rate,
4356 config->format,
4357 channel_count,
4358 is_low_latency);
4359 in->config.period_size = buffer_size / frame_size;
4360 }
4361
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004362 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4363 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4364 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004365 (in->config.rate == 8000 || in->config.rate == 16000 ||
4366 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004367 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4368 voice_extn_compress_voip_open_input_stream(in);
4369 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004370 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004372 /* This stream could be for sound trigger lab,
4373 get sound trigger pcm if present */
4374 audio_extn_sound_trigger_check_and_get_session(in);
4375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004377 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004378 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379
4380err_open:
4381 free(in);
4382 *stream_in = NULL;
4383 return ret;
4384}
4385
4386static void adev_close_input_stream(struct audio_hw_device *dev,
4387 struct audio_stream_in *stream)
4388{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004389 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004390 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004391 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304392
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304393 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004394
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304395 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004396 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304397
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004398 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304399 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004400 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304401 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004402 if (ret != 0)
4403 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4404 __func__, ret);
4405 } else
4406 in_standby(&stream->common);
4407
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004408 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004409 audio_extn_ssr_deinit();
4410 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411
Mingming Yine62d7842013-10-25 16:26:03 -07004412 if(audio_extn_compr_cap_enabled() &&
4413 audio_extn_compr_cap_format_supported(in->config.format))
4414 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004415
Mingming Yinfd7607b2016-01-22 12:48:44 -08004416 if (in->is_st_session) {
4417 ALOGV("%s: sound trigger pcm stop lab", __func__);
4418 audio_extn_sound_trigger_stop_lab(in);
4419 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004420 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 return;
4422}
4423
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004424static int adev_dump(const audio_hw_device_t *device __unused,
4425 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426{
4427 return 0;
4428}
4429
4430static int adev_close(hw_device_t *device)
4431{
4432 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004433
4434 if (!adev)
4435 return 0;
4436
4437 pthread_mutex_lock(&adev_init_lock);
4438
4439 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004440 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004441 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004442 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004443 audio_route_free(adev->audio_route);
4444 free(adev->snd_dev_ref_cnt);
4445 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004446 if (adev->adm_deinit)
4447 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004448 free(device);
4449 adev = NULL;
4450 }
4451 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453 return 0;
4454}
4455
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004456/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4457 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4458 * just that it _might_ work.
4459 */
4460static int period_size_is_plausible_for_low_latency(int period_size)
4461{
4462 switch (period_size) {
4463 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004464 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004465 case 240:
4466 case 320:
4467 case 480:
4468 return 1;
4469 default:
4470 return 0;
4471 }
4472}
4473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474static int adev_open(const hw_module_t *module, const char *name,
4475 hw_device_t **device)
4476{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004477 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4479
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004480 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004481 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004482 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004483 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004484 ALOGD("%s: returning existing instance of adev", __func__);
4485 ALOGD("%s: exit", __func__);
4486 pthread_mutex_unlock(&adev_init_lock);
4487 return 0;
4488 }
4489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490 adev = calloc(1, sizeof(struct audio_device));
4491
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004492 if (!adev) {
4493 pthread_mutex_unlock(&adev_init_lock);
4494 return -ENOMEM;
4495 }
4496
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004497 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004499 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4500 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4501 adev->device.common.module = (struct hw_module_t *)module;
4502 adev->device.common.close = adev_close;
4503
4504 adev->device.init_check = adev_init_check;
4505 adev->device.set_voice_volume = adev_set_voice_volume;
4506 adev->device.set_master_volume = adev_set_master_volume;
4507 adev->device.get_master_volume = adev_get_master_volume;
4508 adev->device.set_master_mute = adev_set_master_mute;
4509 adev->device.get_master_mute = adev_get_master_mute;
4510 adev->device.set_mode = adev_set_mode;
4511 adev->device.set_mic_mute = adev_set_mic_mute;
4512 adev->device.get_mic_mute = adev_get_mic_mute;
4513 adev->device.set_parameters = adev_set_parameters;
4514 adev->device.get_parameters = adev_get_parameters;
4515 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4516 adev->device.open_output_stream = adev_open_output_stream;
4517 adev->device.close_output_stream = adev_close_output_stream;
4518 adev->device.open_input_stream = adev_open_input_stream;
4519 adev->device.close_input_stream = adev_close_input_stream;
4520 adev->device.dump = adev_dump;
4521
4522 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004524 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004525 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004528 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004529 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004530 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004531 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004532 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004533 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004534 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004535 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304536 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304537 adev->perf_lock_opts[0] = 0x101;
4538 adev->perf_lock_opts[1] = 0x20E;
4539 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304540
4541 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4542 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004544 adev->platform = platform_init(adev);
4545 if (!adev->platform) {
4546 free(adev->snd_dev_ref_cnt);
4547 free(adev);
4548 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4549 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004550 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004551 return -EINVAL;
4552 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004553
Naresh Tanniru4c630392014-05-12 01:05:52 +05304554 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4555
Eric Laurentc4aef752013-09-12 17:45:53 -07004556 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4557 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4558 if (adev->visualizer_lib == NULL) {
4559 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4560 } else {
4561 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4562 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004563 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004564 "visualizer_hal_start_output");
4565 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004566 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004567 "visualizer_hal_stop_output");
4568 }
4569 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004570 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004571 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004572
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004573 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4574 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4575 if (adev->offload_effects_lib == NULL) {
4576 ALOGE("%s: DLOPEN failed for %s", __func__,
4577 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4578 } else {
4579 ALOGV("%s: DLOPEN successful for %s", __func__,
4580 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4581 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304582 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004583 "offload_effects_bundle_hal_start_output");
4584 adev->offload_effects_stop_output =
4585 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4586 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004587 adev->offload_effects_set_hpx_state =
4588 (int (*)(bool))dlsym(adev->offload_effects_lib,
4589 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304590 adev->offload_effects_get_parameters =
4591 (void (*)(struct str_parms *, struct str_parms *))
4592 dlsym(adev->offload_effects_lib,
4593 "offload_effects_bundle_get_parameters");
4594 adev->offload_effects_set_parameters =
4595 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4596 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004597 }
4598 }
4599
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004600 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4601 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4602 if (adev->adm_lib == NULL) {
4603 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4604 } else {
4605 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4606 adev->adm_init = (adm_init_t)
4607 dlsym(adev->adm_lib, "adm_init");
4608 adev->adm_deinit = (adm_deinit_t)
4609 dlsym(adev->adm_lib, "adm_deinit");
4610 adev->adm_register_input_stream = (adm_register_input_stream_t)
4611 dlsym(adev->adm_lib, "adm_register_input_stream");
4612 adev->adm_register_output_stream = (adm_register_output_stream_t)
4613 dlsym(adev->adm_lib, "adm_register_output_stream");
4614 adev->adm_deregister_stream = (adm_deregister_stream_t)
4615 dlsym(adev->adm_lib, "adm_deregister_stream");
4616 adev->adm_request_focus = (adm_request_focus_t)
4617 dlsym(adev->adm_lib, "adm_request_focus");
4618 adev->adm_abandon_focus = (adm_abandon_focus_t)
4619 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004620 adev->adm_set_config = (adm_set_config_t)
4621 dlsym(adev->adm_lib, "adm_set_config");
4622 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4623 dlsym(adev->adm_lib, "adm_request_focus_v2");
4624 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4625 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4626 adev->adm_on_routing_change = (adm_on_routing_change_t)
4627 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004628 }
4629 }
4630
Mingming Yin514a8bc2014-07-29 15:22:21 -07004631 adev->bt_wb_speech_enabled = false;
4632
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004633 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 *device = &adev->device.common;
4635
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004636 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4637 &adev->streams_output_cfg_list);
4638
Kiran Kandi910e1862013-10-29 13:29:42 -07004639 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004640
4641 char value[PROPERTY_VALUE_MAX];
4642 int trial;
4643 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4644 trial = atoi(value);
4645 if (period_size_is_plausible_for_low_latency(trial)) {
4646 pcm_config_low_latency.period_size = trial;
4647 pcm_config_low_latency.start_threshold = trial / 4;
4648 pcm_config_low_latency.avail_min = trial / 4;
4649 configured_low_latency_capture_period_size = trial;
4650 }
4651 }
4652 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4653 trial = atoi(value);
4654 if (period_size_is_plausible_for_low_latency(trial)) {
4655 configured_low_latency_capture_period_size = trial;
4656 }
4657 }
4658
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004659 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4660 af_period_multiplier = atoi(value);
4661 if (af_period_multiplier < 0)
4662 af_period_multiplier = 2;
4663 else if (af_period_multiplier > 4)
4664 af_period_multiplier = 4;
4665
4666 ALOGV("new period_multiplier = %d", af_period_multiplier);
4667 }
4668
vivek mehta446c3962015-09-14 10:57:35 -07004669 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004670 pthread_mutex_unlock(&adev_init_lock);
4671
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004672 if (adev->adm_init)
4673 adev->adm_data = adev->adm_init();
4674
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304675 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004676 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 return 0;
4678}
4679
4680static struct hw_module_methods_t hal_module_methods = {
4681 .open = adev_open,
4682};
4683
4684struct audio_module HAL_MODULE_INFO_SYM = {
4685 .common = {
4686 .tag = HARDWARE_MODULE_TAG,
4687 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4688 .hal_api_version = HARDWARE_HAL_API_VERSION,
4689 .id = AUDIO_HARDWARE_MODULE_ID,
4690 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004691 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 .methods = &hal_module_methods,
4693 },
4694};