blob: 69d5cce90e840e5a4fac79386c108d0b54eb4fbf [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);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001365 /* Enable sidetone only if voice/voip call already exists */
1366 if (voice_is_call_state_active(adev) ||
1367 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001368 voice_set_sidetone(adev, out_snd_device, true);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301369 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001370
sangwoo170731f2013-06-08 15:36:36 +09001371 usecase->in_snd_device = in_snd_device;
1372 usecase->out_snd_device = out_snd_device;
1373
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301374 if (usecase->type == PCM_PLAYBACK) {
Amit Shekhar1d896042014-10-03 13:16:09 -07001375 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301376 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07001377 usecase->stream.out->devices,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301378 usecase->stream.out->flags,
1379 usecase->stream.out->format,
1380 usecase->stream.out->sample_rate,
1381 usecase->stream.out->bit_width,
Manish Dewangan837dc462015-05-27 10:17:41 +05301382 usecase->stream.out->channel_mask,
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301383 &usecase->stream.out->app_type_cfg);
Amit Shekhar1d896042014-10-03 13:16:09 -07001384 ALOGI("%s Selected apptype: %d", __func__, usecase->stream.out->app_type_cfg.app_type);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301385 }
Amit Shekhar1d896042014-10-03 13:16:09 -07001386
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001387 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001388
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001389 /* Applicable only on the targets that has external modem.
1390 * Enable device command should be sent to modem only after
1391 * enabling voice call mixer controls
1392 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001393 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001394 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1395 out_snd_device,
1396 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301397 ALOGD("%s: done",__func__);
1398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001399 return status;
1400}
1401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001402static int stop_input_stream(struct stream_in *in)
1403{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301404 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405 struct audio_usecase *uc_info;
1406 struct audio_device *adev = in->dev;
1407
Eric Laurentc8400632013-02-14 19:04:54 -08001408 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409
Eric Laurent994a6932013-07-17 11:51:42 -07001410 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412 uc_info = get_usecase_from_list(adev, in->usecase);
1413 if (uc_info == NULL) {
1414 ALOGE("%s: Could not find the usecase (%d) in the list",
1415 __func__, in->usecase);
1416 return -EINVAL;
1417 }
1418
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001419 /* Close in-call recording streams */
1420 voice_check_and_stop_incall_rec_usecase(adev, in);
1421
Eric Laurent150dbfe2013-02-27 14:31:02 -08001422 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001423 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424
1425 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001426 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001428 list_remove(&uc_info->list);
1429 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430
Eric Laurent994a6932013-07-17 11:51:42 -07001431 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 return ret;
1433}
1434
1435int start_input_stream(struct stream_in *in)
1436{
1437 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001438 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 struct audio_usecase *uc_info;
1440 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301441 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442
Mingming Yin2664a5b2015-09-03 10:53:11 -07001443 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1444 if (get_usecase_from_list(adev, usecase) == NULL)
1445 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301446 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1447 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001448
Naresh Tanniru80659832014-06-04 18:17:56 +05301449
1450 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301451 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301452 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301453 goto error_config;
1454 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301455
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001456 /* Check if source matches incall recording usecase criteria */
1457 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1458 if (ret)
1459 goto error_config;
1460 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001461 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1462
1463 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1464 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1465 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001466 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001467 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001468
Eric Laurentb23d5282013-05-14 15:27:20 -07001469 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470 if (in->pcm_device_id < 0) {
1471 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1472 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001473 ret = -EINVAL;
1474 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476
1477 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001479
1480 if (!uc_info) {
1481 ret = -ENOMEM;
1482 goto error_config;
1483 }
1484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 uc_info->id = in->usecase;
1486 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001487 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001488 uc_info->devices = in->device;
1489 uc_info->in_snd_device = SND_DEVICE_NONE;
1490 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001492 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301493 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1494 adev->perf_lock_opts,
1495 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001496 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301498 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1499 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001500
1501 unsigned int flags = PCM_IN;
1502 unsigned int pcm_open_retry_count = 0;
1503
1504 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1505 flags |= PCM_MMAP | PCM_NOIRQ;
1506 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001507 } else if (in->realtime) {
1508 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001509 }
1510
1511 while (1) {
1512 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1513 flags, &in->config);
1514 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1515 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1516 if (in->pcm != NULL) {
1517 pcm_close(in->pcm);
1518 in->pcm = NULL;
1519 }
1520 if (pcm_open_retry_count-- == 0) {
1521 ret = -EIO;
1522 goto error_open;
1523 }
1524 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1525 continue;
1526 }
1527 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001529
1530 ALOGV("%s: pcm_prepare", __func__);
1531 ret = pcm_prepare(in->pcm);
1532 if (ret < 0) {
1533 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1534 pcm_close(in->pcm);
1535 in->pcm = NULL;
1536 goto error_open;
1537 }
1538
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001539 register_in_stream(in);
1540 if (in->realtime) {
1541 ret = pcm_start(in->pcm);
1542 if (ret < 0)
1543 goto error_open;
1544 }
1545
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301546 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001547 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001548
Eric Laurentc8400632013-02-14 19:04:54 -08001549 return ret;
1550
1551error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301552 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001554error_config:
1555 adev->active_input = NULL;
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301556 /*
1557 * sleep 50ms to allow sufficient time for kernel
1558 * drivers to recover incases like SSR.
1559 */
1560 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001562
1563 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564}
1565
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001566void lock_input_stream(struct stream_in *in)
1567{
1568 pthread_mutex_lock(&in->pre_lock);
1569 pthread_mutex_lock(&in->lock);
1570 pthread_mutex_unlock(&in->pre_lock);
1571}
1572
1573void lock_output_stream(struct stream_out *out)
1574{
1575 pthread_mutex_lock(&out->pre_lock);
1576 pthread_mutex_lock(&out->lock);
1577 pthread_mutex_unlock(&out->pre_lock);
1578}
1579
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001580/* must be called with out->lock locked */
1581static int send_offload_cmd_l(struct stream_out* out, int command)
1582{
1583 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1584
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001585 if (!cmd) {
1586 ALOGE("failed to allocate mem for command 0x%x", command);
1587 return -ENOMEM;
1588 }
1589
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 ALOGVV("%s %d", __func__, command);
1591
1592 cmd->cmd = command;
1593 list_add_tail(&out->offload_cmd_list, &cmd->node);
1594 pthread_cond_signal(&out->offload_cond);
1595 return 0;
1596}
1597
1598/* must be called iwth out->lock locked */
1599static void stop_compressed_output_l(struct stream_out *out)
1600{
1601 out->offload_state = OFFLOAD_STATE_IDLE;
1602 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001603 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001604 if (out->compr != NULL) {
1605 compress_stop(out->compr);
1606 while (out->offload_thread_blocked) {
1607 pthread_cond_wait(&out->cond, &out->lock);
1608 }
1609 }
1610}
1611
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001612bool is_offload_usecase(audio_usecase_t uc_id)
1613{
1614 unsigned int i;
1615 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1616 if (uc_id == offload_usecases[i])
1617 return true;
1618 }
1619 return false;
1620}
1621
vivek mehta446c3962015-09-14 10:57:35 -07001622static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001623{
vivek mehta446c3962015-09-14 10:57:35 -07001624 audio_usecase_t ret_uc = USECASE_INVALID;
1625 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001626 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001627 if (!adev->multi_offload_enable) {
1628 if (is_direct_pcm)
1629 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1630 else
1631 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001632
vivek mehta446c3962015-09-14 10:57:35 -07001633 pthread_mutex_lock(&adev->lock);
1634 if (get_usecase_from_list(adev, ret_uc) != NULL)
1635 ret_uc = USECASE_INVALID;
1636 pthread_mutex_unlock(&adev->lock);
1637
1638 return ret_uc;
1639 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001640
1641 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001642 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1643 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1644 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1645 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001646 break;
1647 }
1648 }
vivek mehta446c3962015-09-14 10:57:35 -07001649
1650 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1651 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001652}
1653
1654static void free_offload_usecase(struct audio_device *adev,
1655 audio_usecase_t uc_id)
1656{
vivek mehta446c3962015-09-14 10:57:35 -07001657 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001658 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001659
1660 if (!adev->multi_offload_enable)
1661 return;
1662
1663 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1664 if (offload_usecases[offload_uc_index] == uc_id) {
1665 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001666 break;
1667 }
1668 }
1669 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1670}
1671
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001672static void *offload_thread_loop(void *context)
1673{
1674 struct stream_out *out = (struct stream_out *) context;
1675 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001676 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001677
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001678 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1679 set_sched_policy(0, SP_FOREGROUND);
1680 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1681
1682 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001683 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684 for (;;) {
1685 struct offload_cmd *cmd = NULL;
1686 stream_callback_event_t event;
1687 bool send_callback = false;
1688
1689 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1690 __func__, list_empty(&out->offload_cmd_list),
1691 out->offload_state);
1692 if (list_empty(&out->offload_cmd_list)) {
1693 ALOGV("%s SLEEPING", __func__);
1694 pthread_cond_wait(&out->offload_cond, &out->lock);
1695 ALOGV("%s RUNNING", __func__);
1696 continue;
1697 }
1698
1699 item = list_head(&out->offload_cmd_list);
1700 cmd = node_to_item(item, struct offload_cmd, node);
1701 list_remove(item);
1702
1703 ALOGVV("%s STATE %d CMD %d out->compr %p",
1704 __func__, out->offload_state, cmd->cmd, out->compr);
1705
1706 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1707 free(cmd);
1708 break;
1709 }
1710
1711 if (out->compr == NULL) {
1712 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07001713 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714 pthread_cond_signal(&out->cond);
1715 continue;
1716 }
1717 out->offload_thread_blocked = true;
1718 pthread_mutex_unlock(&out->lock);
1719 send_callback = false;
1720 switch(cmd->cmd) {
1721 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001722 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001723 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001724 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 send_callback = true;
1726 event = STREAM_CBK_EVENT_WRITE_READY;
1727 break;
1728 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001729 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05301730 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001731 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301732 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001733 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301734 if (ret < 0)
1735 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05301736 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301737 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001738 compress_drain(out->compr);
1739 else
1740 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301741 if (ret != -ENETRESET) {
1742 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301743 pthread_mutex_lock(&out->lock);
1744 out->send_new_metadata = 1;
1745 out->send_next_track_params = true;
1746 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05301747 event = STREAM_CBK_EVENT_DRAIN_READY;
1748 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1749 } else
1750 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 break;
1752 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001753 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07001755 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001756 send_callback = true;
1757 event = STREAM_CBK_EVENT_DRAIN_READY;
1758 break;
1759 default:
1760 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1761 break;
1762 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001763 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 out->offload_thread_blocked = false;
1765 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07001766 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08001767 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001768 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001769 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 free(cmd);
1771 }
1772
1773 pthread_cond_signal(&out->cond);
1774 while (!list_empty(&out->offload_cmd_list)) {
1775 item = list_head(&out->offload_cmd_list);
1776 list_remove(item);
1777 free(node_to_item(item, struct offload_cmd, node));
1778 }
1779 pthread_mutex_unlock(&out->lock);
1780
1781 return NULL;
1782}
1783
1784static int create_offload_callback_thread(struct stream_out *out)
1785{
1786 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1787 list_init(&out->offload_cmd_list);
1788 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1789 offload_thread_loop, out);
1790 return 0;
1791}
1792
1793static int destroy_offload_callback_thread(struct stream_out *out)
1794{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001795 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001796 stop_compressed_output_l(out);
1797 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1798
1799 pthread_mutex_unlock(&out->lock);
1800 pthread_join(out->offload_thread, (void **) NULL);
1801 pthread_cond_destroy(&out->offload_cond);
1802
1803 return 0;
1804}
1805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806static int stop_output_stream(struct stream_out *out)
1807{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301808 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809 struct audio_usecase *uc_info;
1810 struct audio_device *adev = out->dev;
1811
Eric Laurent994a6932013-07-17 11:51:42 -07001812 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 uc_info = get_usecase_from_list(adev, out->usecase);
1815 if (uc_info == NULL) {
1816 ALOGE("%s: Could not find the usecase (%d) in the list",
1817 __func__, out->usecase);
1818 return -EINVAL;
1819 }
1820
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001821 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301822 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001823 if (adev->visualizer_stop_output != NULL)
1824 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001825
1826 audio_extn_dts_remove_state_notifier_node(out->usecase);
1827
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001828 if (adev->offload_effects_stop_output != NULL)
1829 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1830 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001831
Eric Laurent150dbfe2013-02-27 14:31:02 -08001832 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001833 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834
1835 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001836 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001838 list_remove(&uc_info->list);
1839 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001841 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301842 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001843 ALOGV("Disable passthrough , reset mixer to pcm");
1844 /* NO_PASSTHROUGH */
1845 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07001846 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001847 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
1848 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001849
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05301850 /* Must be called after removing the usecase from list */
1851 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301852 audio_extn_keep_alive_start();
1853
Eric Laurent994a6932013-07-17 11:51:42 -07001854 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 return ret;
1856}
1857
1858int start_output_stream(struct stream_out *out)
1859{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 struct audio_usecase *uc_info;
1862 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301863 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001865 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1866 ret = -EINVAL;
1867 goto error_config;
1868 }
1869
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301870 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1871 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1872 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05301873
Naresh Tanniru80659832014-06-04 18:17:56 +05301874 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301875 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301876 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301877 goto error_config;
1878 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301879
Eric Laurentb23d5282013-05-14 15:27:20 -07001880 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 if (out->pcm_device_id < 0) {
1882 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1883 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001884 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07001885 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
1887
1888 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001889
1890 if (!uc_info) {
1891 ret = -ENOMEM;
1892 goto error_config;
1893 }
1894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 uc_info->id = out->usecase;
1896 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001897 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001898 uc_info->devices = out->devices;
1899 uc_info->in_snd_device = SND_DEVICE_NONE;
1900 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001901 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301903 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1904 adev->perf_lock_opts,
1905 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301906
1907 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1908 audio_extn_keep_alive_stop();
1909 if (audio_extn_passthru_is_enabled() &&
1910 audio_extn_passthru_is_passthrough_stream(out)) {
1911 audio_extn_passthru_on_start(out);
1912 audio_extn_passthru_update_stream_configuration(adev, out);
1913 }
1914 }
1915
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916 select_devices(adev, out->usecase);
1917
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001918 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1919 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001920 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001921 unsigned int flags = PCM_OUT;
1922 unsigned int pcm_open_retry_count = 0;
1923 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1924 flags |= PCM_MMAP | PCM_NOIRQ;
1925 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001926 } else if (out->realtime) {
1927 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001928 } else
1929 flags |= PCM_MONOTONIC;
1930
1931 while (1) {
1932 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1933 flags, &out->config);
1934 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1935 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1936 if (out->pcm != NULL) {
1937 pcm_close(out->pcm);
1938 out->pcm = NULL;
1939 }
1940 if (pcm_open_retry_count-- == 0) {
1941 ret = -EIO;
1942 goto error_open;
1943 }
1944 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1945 continue;
1946 }
1947 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001948 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001949
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001950 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1951 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001952
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001953 ALOGV("%s: pcm_prepare", __func__);
1954 if (pcm_is_ready(out->pcm)) {
1955 ret = pcm_prepare(out->pcm);
1956 if (ret < 0) {
1957 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1958 pcm_close(out->pcm);
1959 out->pcm = NULL;
1960 goto error_open;
1961 }
1962 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001963 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001964 platform_set_stream_channel_map(adev->platform, out->channel_mask,
1965 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001967 out->compr = compress_open(adev->snd_card,
1968 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001969 COMPRESS_IN, &out->compr_config);
1970 if (out->compr && !is_compress_ready(out->compr)) {
1971 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1972 compress_close(out->compr);
1973 out->compr = NULL;
1974 ret = -EIO;
1975 goto error_open;
1976 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05301977 /* compress_open sends params of the track, so reset the flag here */
1978 out->is_compr_metadata_avail = false;
1979
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980 if (out->offload_callback)
1981 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001982
Fred Oh3f43e742015-03-04 18:42:34 -08001983 /* Since small bufs uses blocking writes, a write will be blocked
1984 for the default max poll time (20s) in the event of an SSR.
1985 Reduce the poll time to observe and deal with SSR faster.
1986 */
Ashish Jain5106d362016-05-11 19:23:33 +05301987 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08001988 compress_set_max_poll_wait(out->compr, 1000);
1989 }
1990
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08001991 audio_extn_dts_create_state_notifier_node(out->usecase);
1992 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
1993 popcount(out->channel_mask),
1994 out->playback_started);
1995
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001996#ifdef DS1_DOLBY_DDP_ENABLED
1997 if (audio_extn_is_dolby_format(out->format))
1998 audio_extn_dolby_send_ddp_endp_params(adev);
1999#endif
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302000 if (!(audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002001 if (adev->visualizer_start_output != NULL)
2002 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2003 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302004 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002005 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002006 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002008
2009 if (ret == 0) {
2010 register_out_stream(out);
2011 if (out->realtime) {
2012 ret = pcm_start(out->pcm);
2013 if (ret < 0)
2014 goto error_open;
2015 }
2016 }
2017
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302018 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002019 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002020
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002021 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302023 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002025error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302026 /*
2027 * sleep 50ms to allow sufficient time for kernel
2028 * drivers to recover incases like SSR.
2029 */
2030 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002031 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032}
2033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034static int check_input_parameters(uint32_t sample_rate,
2035 audio_format_t format,
2036 int channel_count)
2037{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002038 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002039
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302040 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2041 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2042 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002043 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302044 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002045
2046 switch (channel_count) {
2047 case 1:
2048 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302049 case 3:
2050 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002051 case 6:
2052 break;
2053 default:
2054 ret = -EINVAL;
2055 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056
2057 switch (sample_rate) {
2058 case 8000:
2059 case 11025:
2060 case 12000:
2061 case 16000:
2062 case 22050:
2063 case 24000:
2064 case 32000:
2065 case 44100:
2066 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302067 case 96000:
2068 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069 break;
2070 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002071 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 }
2073
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075}
2076
2077static size_t get_input_buffer_size(uint32_t sample_rate,
2078 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002079 int channel_count,
2080 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081{
2082 size_t size = 0;
2083
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002084 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2085 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002087 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002088 if (is_low_latency)
2089 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302090
2091 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002093 /* make sure the size is multiple of 32 bytes
2094 * At 48 kHz mono 16-bit PCM:
2095 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2096 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2097 */
2098 size += 0x1f;
2099 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002100
2101 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102}
2103
Ashish Jain5106d362016-05-11 19:23:33 +05302104static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2105{
2106 uint64_t actual_frames_rendered = 0;
2107 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2108
2109 /* This adjustment accounts for buffering after app processor.
2110 * It is based on estimated DSP latency per use case, rather than exact.
2111 */
2112 int64_t platform_latency = platform_render_latency(out->usecase) *
2113 out->sample_rate / 1000000LL;
2114
2115 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2116 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2117 * hence only estimate.
2118 */
2119 int64_t signed_frames = out->written - kernel_buffer_size;
2120
2121 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2122
2123 if (signed_frames > 0)
2124 actual_frames_rendered = signed_frames;
2125
2126 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2127 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2128 (long long int)out->written, (int)kernel_buffer_size,
2129 audio_bytes_per_sample(out->compr_config.codec->format),
2130 popcount(out->channel_mask));
2131
2132 return actual_frames_rendered;
2133}
2134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002135static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2136{
2137 struct stream_out *out = (struct stream_out *)stream;
2138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140}
2141
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002142static int out_set_sample_rate(struct audio_stream *stream __unused,
2143 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144{
2145 return -ENOSYS;
2146}
2147
2148static size_t out_get_buffer_size(const struct audio_stream *stream)
2149{
2150 struct stream_out *out = (struct stream_out *)stream;
2151
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002152 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002154 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2155 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302156 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302157 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002159 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002160 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161}
2162
2163static uint32_t out_get_channels(const struct audio_stream *stream)
2164{
2165 struct stream_out *out = (struct stream_out *)stream;
2166
2167 return out->channel_mask;
2168}
2169
2170static audio_format_t out_get_format(const struct audio_stream *stream)
2171{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002172 struct stream_out *out = (struct stream_out *)stream;
2173
2174 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175}
2176
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002177static int out_set_format(struct audio_stream *stream __unused,
2178 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179{
2180 return -ENOSYS;
2181}
2182
2183static int out_standby(struct audio_stream *stream)
2184{
2185 struct stream_out *out = (struct stream_out *)stream;
2186 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302188 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2189 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002191 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002193 if (adev->adm_deregister_stream)
2194 adev->adm_deregister_stream(adev->adm_data, out->handle);
2195
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002196 if (is_offload_usecase(out->usecase))
2197 stop_compressed_output_l(out);
2198
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002199 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002201 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2202 voice_extn_compress_voip_close_output_stream(stream);
2203 pthread_mutex_unlock(&adev->lock);
2204 pthread_mutex_unlock(&out->lock);
2205 ALOGD("VOIP output entered standby");
2206 return 0;
2207 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 if (out->pcm) {
2209 pcm_close(out->pcm);
2210 out->pcm = NULL;
2211 }
2212 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002213 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302214 out->send_next_track_params = false;
2215 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002216 out->gapless_mdata.encoder_delay = 0;
2217 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002218 if (out->compr != NULL) {
2219 compress_close(out->compr);
2220 out->compr = NULL;
2221 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002222 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002224 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 }
2226 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302227 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 return 0;
2229}
2230
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002231static int out_dump(const struct audio_stream *stream __unused,
2232 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233{
2234 return 0;
2235}
2236
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002237static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2238{
2239 int ret = 0;
2240 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002241
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002242 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002243 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002244 return -EINVAL;
2245 }
2246
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302247 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002248
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002249 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2250 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302251 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002252 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002253 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2254 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302255 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002256 }
2257
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002258 ALOGV("%s new encoder delay %u and padding %u", __func__,
2259 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2260
2261 return 0;
2262}
2263
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002264static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2265{
2266 return out == adev->primary_output || out == adev->voice_tx_output;
2267}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2270{
2271 struct stream_out *out = (struct stream_out *)stream;
2272 struct audio_device *adev = out->dev;
2273 struct str_parms *parms;
2274 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002275 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276
sangwoobc677242013-08-08 16:53:43 +09002277 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002278 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302280 if (!parms)
2281 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002282 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2283 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002285 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002286 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002288 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002289 * When HDMI cable is unplugged the music playback is paused and
2290 * the policy manager sends routing=0. But the audioflinger continues
2291 * to write data until standby time (3sec). As the HDMI core is
2292 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002293 * Avoid this by routing audio to speaker until standby.
2294 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002295 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2296 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302297 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002298 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2299 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002300 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302301 /*
2302 * When A2DP is disconnected the
2303 * music playback is paused and the policy manager sends routing=0
2304 * But the audioflingercontinues to write data until standby time
2305 * (3sec). As BT is turned off, the write gets blocked.
2306 * Avoid this by routing audio to speaker until standby.
2307 */
2308 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2309 (val == AUDIO_DEVICE_NONE)) {
2310 val = AUDIO_DEVICE_OUT_SPEAKER;
2311 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002312
2313 /*
2314 * select_devices() call below switches all the usecases on the same
2315 * backend to the new device. Refer to check_usecases_codec_backend() in
2316 * the select_devices(). But how do we undo this?
2317 *
2318 * For example, music playback is active on headset (deep-buffer usecase)
2319 * and if we go to ringtones and select a ringtone, low-latency usecase
2320 * will be started on headset+speaker. As we can't enable headset+speaker
2321 * and headset devices at the same time, select_devices() switches the music
2322 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2323 * So when the ringtone playback is completed, how do we undo the same?
2324 *
2325 * We are relying on the out_set_parameters() call on deep-buffer output,
2326 * once the ringtone playback is ended.
2327 * NOTE: We should not check if the current devices are same as new devices.
2328 * Because select_devices() must be called to switch back the music
2329 * playback to headset.
2330 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002331 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002332 audio_devices_t new_dev = val;
2333 bool same_dev = out->devices == new_dev;
2334 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002335
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002336 if (output_drives_call(adev, out)) {
2337 if(!voice_is_in_call(adev)) {
2338 if (adev->mode == AUDIO_MODE_IN_CALL) {
2339 adev->current_call_output = out;
2340 ret = voice_start_call(adev);
2341 }
2342 } else {
2343 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002344 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002345 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002346 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002347
2348 if (!out->standby) {
2349 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2350 adev->perf_lock_opts,
2351 adev->perf_lock_opts_size);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002352 if (!same_dev) {
2353 ALOGV("update routing change");
2354 out->routing_change = true;
2355 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002356 select_devices(adev, out->usecase);
2357 audio_extn_perf_lock_release(&adev->perf_lock_handle);
2358 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002359 }
2360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002362 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002364
2365 if (out == adev->primary_output) {
2366 pthread_mutex_lock(&adev->lock);
2367 audio_extn_set_parameters(adev, parms);
2368 pthread_mutex_unlock(&adev->lock);
2369 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002370 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002371 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002372 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002373
2374 audio_extn_dts_create_state_notifier_node(out->usecase);
2375 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2376 popcount(out->channel_mask),
2377 out->playback_started);
2378
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002379 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002380 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302383error:
Eric Laurent994a6932013-07-17 11:51:42 -07002384 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 return ret;
2386}
2387
2388static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2389{
2390 struct stream_out *out = (struct stream_out *)stream;
2391 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002392 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 char value[256];
2394 struct str_parms *reply = str_parms_create();
2395 size_t i, j;
2396 int ret;
2397 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002398
2399 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002400 if (reply) {
2401 str_parms_destroy(reply);
2402 }
2403 if (query) {
2404 str_parms_destroy(query);
2405 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002406 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2407 return NULL;
2408 }
2409
Eric Laurent994a6932013-07-17 11:51:42 -07002410 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2412 if (ret >= 0) {
2413 value[0] = '\0';
2414 i = 0;
2415 while (out->supported_channel_masks[i] != 0) {
2416 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2417 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2418 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002419 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002421 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422 first = false;
2423 break;
2424 }
2425 }
2426 i++;
2427 }
2428 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2429 str = str_parms_to_str(reply);
2430 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002431 voice_extn_out_get_parameters(out, query, reply);
2432 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002433 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002434 free(str);
2435 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002436 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002438
Alexy Joseph62142aa2015-11-16 15:10:34 -08002439
2440 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2441 if (ret >= 0) {
2442 value[0] = '\0';
2443 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2444 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302445 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002446 } else {
2447 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302448 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002449 }
2450 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002451 if (str)
2452 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002453 str = str_parms_to_str(reply);
2454 }
2455
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002456 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2457 if (ret >= 0) {
2458 value[0] = '\0';
2459 i = 0;
2460 first = true;
2461 while (out->supported_formats[i] != 0) {
2462 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2463 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2464 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002465 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002466 }
2467 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2468 first = false;
2469 break;
2470 }
2471 }
2472 i++;
2473 }
2474 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002475 if (str)
2476 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002477 str = str_parms_to_str(reply);
2478 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002479
2480 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2481 if (ret >= 0) {
2482 value[0] = '\0';
2483 i = 0;
2484 first = true;
2485 while (out->supported_sample_rates[i] != 0) {
2486 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2487 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2488 if (!first) {
2489 strlcat(value, "|", sizeof(value));
2490 }
2491 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2492 first = false;
2493 break;
2494 }
2495 }
2496 i++;
2497 }
2498 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2499 if (str)
2500 free(str);
2501 str = str_parms_to_str(reply);
2502 }
2503
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 str_parms_destroy(query);
2505 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002506 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 return str;
2508}
2509
2510static uint32_t out_get_latency(const struct audio_stream_out *stream)
2511{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002512 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002514 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515
Alexy Josephaa54c872014-12-03 02:46:47 -08002516 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002517 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002518 } else if (out->realtime) {
2519 // since the buffer won't be filled up faster than realtime,
2520 // return a smaller number
2521 if (out->config.rate)
2522 period_ms = (out->af_period_multiplier * out->config.period_size *
2523 1000) / (out->config.rate);
2524 else
2525 period_ms = 0;
2526 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002527 } else {
2528 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002529 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002530 }
2531
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302532 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002533 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534}
2535
2536static int out_set_volume(struct audio_stream_out *stream, float left,
2537 float right)
2538{
Eric Laurenta9024de2013-04-04 09:19:12 -07002539 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002540 int volume[2];
2541
Eric Laurenta9024de2013-04-04 09:19:12 -07002542 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2543 /* only take left channel into account: the API is for stereo anyway */
2544 out->muted = (left == 0.0f);
2545 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002546 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302547 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002548 /*
2549 * Set mute or umute on HDMI passthrough stream.
2550 * Only take left channel into account.
2551 * Mute is 0 and unmute 1
2552 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302553 audio_extn_passthru_set_volume(out, (left == 0.0f));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002554 } else {
2555 char mixer_ctl_name[128];
2556 struct audio_device *adev = out->dev;
2557 struct mixer_ctl *ctl;
2558 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002559 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002560
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002561 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2562 "Compress Playback %d Volume", pcm_device_id);
2563 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2564 if (!ctl) {
2565 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2566 __func__, mixer_ctl_name);
2567 return -EINVAL;
2568 }
2569 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2570 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2571 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2572 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002573 }
Eric Laurenta9024de2013-04-04 09:19:12 -07002574 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 return -ENOSYS;
2577}
2578
2579static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2580 size_t bytes)
2581{
2582 struct stream_out *out = (struct stream_out *)stream;
2583 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302584 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002585 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002587 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302588
Naresh Tanniru80659832014-06-04 18:17:56 +05302589 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08002590
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05302591 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05302592 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05302593 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2594 pthread_mutex_unlock(&out->lock);
2595 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05302596 } else {
2597 /* increase written size during SSR to avoid mismatch
2598 * with the written frames count in AF
2599 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05302600 if (audio_bytes_per_sample(out->format) != 0)
2601 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
Ashish Jainbbce4322016-02-16 13:25:27 +05302602 ALOGD(" %s: sound card is not active/SSR state", __func__);
2603 ret= -EIO;
2604 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302605 }
2606 }
2607
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302608 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302609 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
2610 if (audio_bytes_per_sample(out->format) != 0)
2611 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2612 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302613 goto exit;
2614 }
2615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002617 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002618 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002619 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2620 ret = voice_extn_compress_voip_start_output_stream(out);
2621 else
2622 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002623 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002626 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 goto exit;
2628 }
vivek mehtab72d08d2016-04-29 03:16:47 -07002629
2630 if (last_known_cal_step != -1) {
2631 ALOGD("%s: retry previous failed cal level set", __func__);
2632 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635
Ashish Jain81eb2a82015-05-13 10:52:34 +05302636 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08002637 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05302638 adev->is_channel_status_set = true;
2639 }
2640
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002641 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08002642 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002643 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002644 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002645 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2646 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302647 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2648 ALOGD("copl(%p):send next track params in gapless", out);
2649 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2650 out->send_next_track_params = false;
2651 out->is_compr_metadata_avail = false;
2652 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002653 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05302654 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302655 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002656
Ashish Jain83a6cc22016-06-28 14:34:17 +05302657 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05302658 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05302659 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302660 pthread_mutex_unlock(&out->lock);
2661 return -EINVAL;
2662 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05302663 audio_format_t dst_format = out->hal_op_format;
2664 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05302665
2666 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
2667 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
2668
Ashish Jain83a6cc22016-06-28 14:34:17 +05302669 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302670 dst_format,
2671 buffer,
2672 src_format,
2673 frames);
2674
Ashish Jain83a6cc22016-06-28 14:34:17 +05302675 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05302676 bytes_to_write);
2677
2678 /*Convert written bytes in audio flinger format*/
2679 if (ret > 0)
2680 ret = ((ret * format_to_bitwidth_table[out->format]) /
2681 format_to_bitwidth_table[dst_format]);
2682 }
2683 } else
2684 ret = compress_write(out->compr, buffer, bytes);
2685
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302686 if (ret < 0)
2687 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302688 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002689 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05302690 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002691 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05302692 } else if (-ENETRESET == ret) {
2693 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2694 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2695 pthread_mutex_unlock(&out->lock);
2696 out_standby(&out->stream.common);
2697 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002698 }
Ashish Jain5106d362016-05-11 19:23:33 +05302699 if ( ret == (ssize_t)bytes && !out->non_blocking)
2700 out->written += bytes;
2701
Naresh Tanniru80659832014-06-04 18:17:56 +05302702 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002703 compress_start(out->compr);
Alexy Joseph7de344d2015-03-30 10:40:03 -07002704 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002705 out->playback_started = 1;
2706 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002707
2708 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2709 popcount(out->channel_mask),
2710 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002711 }
2712 pthread_mutex_unlock(&out->lock);
2713 return ret;
2714 } else {
2715 if (out->pcm) {
2716 if (out->muted)
2717 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002718
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302719 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002720
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002721 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002722
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002723 if (out->config.rate)
2724 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2725 out->config.rate;
2726
2727 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2728
2729 request_out_focus(out, ns);
2730
2731 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002732 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002733 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05302734 out->convert_buffer != NULL) {
2735
2736 memcpy_by_audio_format(out->convert_buffer,
2737 out->hal_op_format,
2738 buffer,
2739 out->hal_ip_format,
2740 out->config.period_size * out->config.channels);
2741
2742 ret = pcm_write(out->pcm, out->convert_buffer,
2743 (out->config.period_size *
2744 out->config.channels *
2745 format_to_bitwidth_table[out->hal_op_format]));
2746 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002747 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05302748 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002749
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002750 release_out_focus(out);
2751
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302752 if (ret < 0)
2753 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05302754 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
2755 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
2756 else
2757 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002758 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 }
2760
2761exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05302762 /* ToDo: There may be a corner case when SSR happens back to back during
2763 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05302764 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302765 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302766 }
2767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 pthread_mutex_unlock(&out->lock);
2769
2770 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002771 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08002772 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302773 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302774 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302775 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05302776 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05302777 out->standby = true;
2778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779 out_standby(&out->stream.common);
Ashish Jainbbce4322016-02-16 13:25:27 +05302780 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05302781 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 }
2783 return bytes;
2784}
2785
2786static int out_get_render_position(const struct audio_stream_out *stream,
2787 uint32_t *dsp_frames)
2788{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002789 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302790 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08002791
2792 if (dsp_frames == NULL)
2793 return -EINVAL;
2794
2795 *dsp_frames = 0;
2796 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08002797 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05302798
2799 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
2800 * this operation and adev_close_output_stream(where out gets reset).
2801 */
2802 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2803 *dsp_frames = get_actual_pcm_frames_rendered(out);
2804 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
2805 return 0;
2806 }
2807
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002808 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05302809 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302810 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002811 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05302812 if (ret < 0)
2813 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002814 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05302815 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002816 }
2817 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05302818 if (-ENETRESET == ret) {
2819 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2820 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2821 return -EINVAL;
2822 } else if(ret < 0) {
2823 ALOGE(" ERROR: Unable to get time stamp from compress driver");
2824 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302825 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
2826 /*
2827 * Handle corner case where compress session is closed during SSR
2828 * and timestamp is queried
2829 */
2830 ALOGE(" ERROR: sound card not active, return error");
2831 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05302832 } else {
2833 return 0;
2834 }
Zhou Song32a556e2015-05-05 10:46:56 +08002835 } else if (audio_is_linear_pcm(out->format)) {
2836 *dsp_frames = out->written;
2837 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 } else
2839 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840}
2841
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002842static int out_add_audio_effect(const struct audio_stream *stream __unused,
2843 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844{
2845 return 0;
2846}
2847
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002848static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2849 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850{
2851 return 0;
2852}
2853
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002854static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2855 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856{
2857 return -EINVAL;
2858}
2859
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002860static int out_get_presentation_position(const struct audio_stream_out *stream,
2861 uint64_t *frames, struct timespec *timestamp)
2862{
2863 struct stream_out *out = (struct stream_out *)stream;
2864 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002865 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002866
Ashish Jain5106d362016-05-11 19:23:33 +05302867 /* below piece of code is not guarded against any lock because audioFliner serializes
2868 * this operation and adev_close_output_stream( where out gets reset).
2869 */
2870 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
2871 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
2872 *frames = get_actual_pcm_frames_rendered(out);
2873 /* this is the best we can do */
2874 clock_gettime(CLOCK_MONOTONIC, timestamp);
2875 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
2876 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
2877 return 0;
2878 }
2879
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002880 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002881
Ashish Jain5106d362016-05-11 19:23:33 +05302882 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
2883 ret = compress_get_tstamp(out->compr, &dsp_frames,
2884 &out->sample_rate);
2885 ALOGVV("%s rendered frames %ld sample_rate %d",
2886 __func__, dsp_frames, out->sample_rate);
2887 *frames = dsp_frames;
2888 if (ret < 0)
2889 ret = -errno;
2890 if (-ENETRESET == ret) {
2891 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2892 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2893 ret = -EINVAL;
2894 } else
2895 ret = 0;
2896 /* this is the best we can do */
2897 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07002898 } else {
2899 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002900 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002901 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2902 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002903 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002904 // This adjustment accounts for buffering after app processor.
2905 // It is based on estimated DSP latency per use case, rather than exact.
2906 signed_frames -=
2907 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2908
Eric Laurent949a0892013-09-20 09:20:13 -07002909 // It would be unusual for this value to be negative, but check just in case ...
2910 if (signed_frames >= 0) {
2911 *frames = signed_frames;
2912 ret = 0;
2913 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002914 }
Ashish Jainbbce4322016-02-16 13:25:27 +05302915 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
2916 *frames = out->written;
2917 clock_gettime(CLOCK_MONOTONIC, timestamp);
2918 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002919 }
2920 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002921 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002922 return ret;
2923}
2924
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002925static int out_set_callback(struct audio_stream_out *stream,
2926 stream_callback_t callback, void *cookie)
2927{
2928 struct stream_out *out = (struct stream_out *)stream;
2929
2930 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002931 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002932 out->offload_callback = callback;
2933 out->offload_cookie = cookie;
2934 pthread_mutex_unlock(&out->lock);
2935 return 0;
2936}
2937
2938static int out_pause(struct audio_stream_out* stream)
2939{
2940 struct stream_out *out = (struct stream_out *)stream;
2941 int status = -ENOSYS;
2942 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002943 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002944 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002945 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002946 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302947 struct audio_device *adev = out->dev;
2948 int snd_scard_state = get_snd_card_state(adev);
2949
2950 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2951 status = compress_pause(out->compr);
2952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002953 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002954
Mingming Yin21854652016-04-13 11:54:02 -07002955 if (audio_extn_passthru_is_active()) {
2956 ALOGV("offload use case, pause passthru");
2957 audio_extn_passthru_on_pause(out);
2958 }
2959
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302960 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002961 audio_extn_dts_notify_playback_state(out->usecase, 0,
2962 out->sample_rate, popcount(out->channel_mask),
2963 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002964 }
2965 pthread_mutex_unlock(&out->lock);
2966 }
2967 return status;
2968}
2969
2970static int out_resume(struct audio_stream_out* stream)
2971{
2972 struct stream_out *out = (struct stream_out *)stream;
2973 int status = -ENOSYS;
2974 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002975 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002976 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002977 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002978 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002979 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05302980 struct audio_device *adev = out->dev;
2981 int snd_scard_state = get_snd_card_state(adev);
2982
Mingming Yin21854652016-04-13 11:54:02 -07002983 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
2984 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2985 pthread_mutex_lock(&out->dev->lock);
2986 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07002987 pthread_mutex_unlock(&out->dev->lock);
2988 }
Naresh Tanniru80659832014-06-04 18:17:56 +05302989 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07002990 }
2991 if (!status) {
2992 out->offload_state = OFFLOAD_STATE_PLAYING;
2993 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05302994 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002995 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2996 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002997 }
2998 pthread_mutex_unlock(&out->lock);
2999 }
3000 return status;
3001}
3002
3003static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3004{
3005 struct stream_out *out = (struct stream_out *)stream;
3006 int status = -ENOSYS;
3007 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003008 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003009 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003010 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3011 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3012 else
3013 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3014 pthread_mutex_unlock(&out->lock);
3015 }
3016 return status;
3017}
3018
3019static int out_flush(struct audio_stream_out* stream)
3020{
3021 struct stream_out *out = (struct stream_out *)stream;
3022 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003023 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003024 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003025 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003026 stop_compressed_output_l(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303027 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003028 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003029 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 return 0;
3031 }
3032 return -ENOSYS;
3033}
3034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035/** audio_stream_in implementation **/
3036static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3037{
3038 struct stream_in *in = (struct stream_in *)stream;
3039
3040 return in->config.rate;
3041}
3042
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003043static int in_set_sample_rate(struct audio_stream *stream __unused,
3044 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045{
3046 return -ENOSYS;
3047}
3048
3049static size_t in_get_buffer_size(const struct audio_stream *stream)
3050{
3051 struct stream_in *in = (struct stream_in *)stream;
3052
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003053 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3054 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003055 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3056 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003057
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003058 return in->config.period_size * in->af_period_multiplier *
3059 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060}
3061
3062static uint32_t in_get_channels(const struct audio_stream *stream)
3063{
3064 struct stream_in *in = (struct stream_in *)stream;
3065
3066 return in->channel_mask;
3067}
3068
3069static audio_format_t in_get_format(const struct audio_stream *stream)
3070{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003071 struct stream_in *in = (struct stream_in *)stream;
3072
3073 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074}
3075
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003076static int in_set_format(struct audio_stream *stream __unused,
3077 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078{
3079 return -ENOSYS;
3080}
3081
3082static int in_standby(struct audio_stream *stream)
3083{
3084 struct stream_in *in = (struct stream_in *)stream;
3085 struct audio_device *adev = in->dev;
3086 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303087 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3088 stream, in->usecase, use_case_table[in->usecase]);
3089
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003090 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003091 if (!in->standby && in->is_st_session) {
3092 ALOGD("%s: sound trigger pcm stop lab", __func__);
3093 audio_extn_sound_trigger_stop_lab(in);
3094 in->standby = 1;
3095 }
3096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003098 if (adev->adm_deregister_stream)
3099 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3100
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003101 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003103 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3104 voice_extn_compress_voip_close_input_stream(stream);
3105 ALOGD("VOIP input entered standby");
3106 } else {
3107 if (in->pcm) {
3108 pcm_close(in->pcm);
3109 in->pcm = NULL;
3110 }
3111 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003112 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003113 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 }
3115 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003116 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 return status;
3118}
3119
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003120static int in_dump(const struct audio_stream *stream __unused,
3121 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122{
3123 return 0;
3124}
3125
3126static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3127{
3128 struct stream_in *in = (struct stream_in *)stream;
3129 struct audio_device *adev = in->dev;
3130 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003132 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303134 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 parms = str_parms_create_str(kvpairs);
3136
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303137 if (!parms)
3138 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003139 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003140 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003141
3142 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3143 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 val = atoi(value);
3145 /* no audio source uses val == 0 */
3146 if ((in->source != val) && (val != 0)) {
3147 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003148 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3149 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3150 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003151 (in->config.rate == 8000 || in->config.rate == 16000 ||
3152 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003153 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003154 err = voice_extn_compress_voip_open_input_stream(in);
3155 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003156 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003157 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003158 }
3159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160 }
3161 }
3162
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003163 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3164 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003166 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 in->device = val;
3168 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003169 if (!in->standby && !in->is_st_session) {
3170 ALOGV("update input routing change");
3171 in->routing_change = true;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003172 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 }
3175 }
3176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003178 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179
3180 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303181error:
Eric Laurent994a6932013-07-17 11:51:42 -07003182 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003183 return ret;
3184}
3185
3186static char* in_get_parameters(const struct audio_stream *stream,
3187 const char *keys)
3188{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003189 struct stream_in *in = (struct stream_in *)stream;
3190 struct str_parms *query = str_parms_create_str(keys);
3191 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003192 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003193
3194 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003195 if (reply) {
3196 str_parms_destroy(reply);
3197 }
3198 if (query) {
3199 str_parms_destroy(query);
3200 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003201 ALOGE("in_get_parameters: failed to create query or reply");
3202 return NULL;
3203 }
3204
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003205 ALOGV("%s: enter: keys - %s", __func__, keys);
3206
3207 voice_extn_in_get_parameters(in, query, reply);
3208
3209 str = str_parms_to_str(reply);
3210 str_parms_destroy(query);
3211 str_parms_destroy(reply);
3212
3213 ALOGV("%s: exit: returns - %s", __func__, str);
3214 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215}
3216
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003217static int in_set_gain(struct audio_stream_in *stream __unused,
3218 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219{
3220 return 0;
3221}
3222
3223static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3224 size_t bytes)
3225{
3226 struct stream_in *in = (struct stream_in *)stream;
3227 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303228 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303229 int snd_scard_state = get_snd_card_state(adev);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303230 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003232 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303233
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003234 if (in->is_st_session) {
3235 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3236 /* Read from sound trigger HAL */
3237 audio_extn_sound_trigger_read(in, buffer, bytes);
3238 pthread_mutex_unlock(&in->lock);
3239 return bytes;
3240 }
3241
Ashish Jainbbce4322016-02-16 13:25:27 +05303242 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003243 ALOGD(" %s: sound card is not active/SSR state", __func__);
3244 ret= -EIO;;
3245 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303246 }
3247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003249 pthread_mutex_lock(&adev->lock);
3250 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3251 ret = voice_extn_compress_voip_start_input_stream(in);
3252 else
3253 ret = start_input_stream(in);
3254 pthread_mutex_unlock(&adev->lock);
3255 if (ret != 0) {
3256 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 }
3258 in->standby = 0;
3259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003261 // what's the duration requested by the client?
3262 long ns = 0;
3263
3264 if (in->config.rate)
3265 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3266 in->config.rate;
3267
3268 request_in_focus(in, ns);
3269 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303272 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003273 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303274 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003275 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003276 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003277 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303278 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003279 ret = pcm_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303280 if ( !ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3281 if (bytes % 4 == 0) {
3282 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3283 int_buf_stream = buffer;
3284 for (size_t itt=0; itt < bytes/4 ; itt++) {
3285 int_buf_stream[itt] >>= 8;
3286 }
3287 } else {
3288 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3289 ret = -EINVAL;
3290 goto exit;
3291 }
3292 } if (ret < 0) {
3293 ret = -errno;
3294 }
3295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 }
3297
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003298 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 /*
3301 * Instead of writing zeroes here, we could trust the hardware
3302 * to always provide zeroes when muted.
3303 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303304 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3305 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306 memset(buffer, 0, bytes);
3307
3308exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303309 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303310 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003311 if (-ENETRESET == ret)
3312 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 pthread_mutex_unlock(&in->lock);
3315
3316 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303317 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303318 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303319 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303320 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303321 in->standby = true;
3322 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303323 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003325 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303326 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303327 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 }
3329 return bytes;
3330}
3331
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003332static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333{
3334 return 0;
3335}
3336
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003337static int add_remove_audio_effect(const struct audio_stream *stream,
3338 effect_handle_t effect,
3339 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003341 struct stream_in *in = (struct stream_in *)stream;
3342 int status = 0;
3343 effect_descriptor_t desc;
3344
3345 status = (*effect)->get_descriptor(effect, &desc);
3346 if (status != 0)
3347 return status;
3348
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003349 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003350 pthread_mutex_lock(&in->dev->lock);
3351 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3352 in->enable_aec != enable &&
3353 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3354 in->enable_aec = enable;
3355 if (!in->standby)
3356 select_devices(in->dev, in->usecase);
3357 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003358 if (in->enable_ns != enable &&
3359 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3360 in->enable_ns = enable;
3361 if (!in->standby)
3362 select_devices(in->dev, in->usecase);
3363 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003364 pthread_mutex_unlock(&in->dev->lock);
3365 pthread_mutex_unlock(&in->lock);
3366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 return 0;
3368}
3369
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003370static int in_add_audio_effect(const struct audio_stream *stream,
3371 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372{
Eric Laurent994a6932013-07-17 11:51:42 -07003373 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003374 return add_remove_audio_effect(stream, effect, true);
3375}
3376
3377static int in_remove_audio_effect(const struct audio_stream *stream,
3378 effect_handle_t effect)
3379{
Eric Laurent994a6932013-07-17 11:51:42 -07003380 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003381 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382}
3383
3384static int adev_open_output_stream(struct audio_hw_device *dev,
3385 audio_io_handle_t handle,
3386 audio_devices_t devices,
3387 audio_output_flags_t flags,
3388 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003389 struct audio_stream_out **stream_out,
3390 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391{
3392 struct audio_device *adev = (struct audio_device *)dev;
3393 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303394 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003395 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303398
3399 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3400 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003401 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303402 return -EINVAL;
3403 }
3404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3406
Mingming Yin3a941d42016-02-17 18:08:05 -08003407 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3408 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303409 devices, flags, &out->stream);
3410
3411
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003412 if (!out) {
3413 return -ENOMEM;
3414 }
3415
Haynes Mathew George204045b2015-02-25 20:32:03 -08003416 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003417 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003418 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 if (devices == AUDIO_DEVICE_NONE)
3421 devices = AUDIO_DEVICE_OUT_SPEAKER;
3422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 out->flags = flags;
3424 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003425 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003426 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003427 out->sample_rate = config->sample_rate;
3428 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3429 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003430 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003431 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003432 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303433 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434
Mingming Yin3a941d42016-02-17 18:08:05 -08003435 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3436 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3437 pthread_mutex_lock(&adev->lock);
3438 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3439 ret = read_hdmi_sink_caps(out);
3440 pthread_mutex_unlock(&adev->lock);
3441 if (ret != 0) {
3442 if (ret == -ENOSYS) {
3443 /* ignore and go with default */
3444 ret = 0;
3445 } else {
3446 ALOGE("error reading hdmi sink caps");
3447 goto error_open;
3448 }
3449 }
3450 }
3451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003453 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303454 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3455 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003456 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3457 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3458
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003459 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003460 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3461 /*
3462 * Do not handle stereo output in Multi-channel cases
3463 * Stereo case is handled in normal playback path
3464 */
3465 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3466 ret = AUDIO_CHANNEL_OUT_STEREO;
3467 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003468
3469 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3470 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003471 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003472 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003473 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003474
3475 if (config->sample_rate == 0)
3476 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3477 if (config->channel_mask == 0)
3478 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003479 if (config->format == 0)
3480 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003481
3482 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003483 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003484 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3486 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003488 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003490 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3491 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003492 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003493 ret = voice_extn_compress_voip_open_output_stream(out);
3494 if (ret != 0) {
3495 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3496 __func__, ret);
3497 goto error_open;
3498 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003499 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3500 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3501
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3503 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3504 ALOGE("%s: Unsupported Offload information", __func__);
3505 ret = -EINVAL;
3506 goto error_open;
3507 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003508
Mingming Yin3a941d42016-02-17 18:08:05 -08003509 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003510 if(config->offload_info.format == 0)
3511 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003512 if (config->offload_info.sample_rate == 0)
3513 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003514 }
3515
Mingming Yin90310102013-11-13 16:57:00 -08003516 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303517 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003518 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003519 ret = -EINVAL;
3520 goto error_open;
3521 }
3522
3523 out->compr_config.codec = (struct snd_codec *)
3524 calloc(1, sizeof(struct snd_codec));
3525
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003526 if (!out->compr_config.codec) {
3527 ret = -ENOMEM;
3528 goto error_open;
3529 }
3530
vivek mehta0ea887a2015-08-26 14:01:20 -07003531 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05303532 out->stream.pause = out_pause;
3533 out->stream.flush = out_flush;
3534 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07003535 out->usecase = get_offload_usecase(adev, true);
3536 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003537 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07003538 out->stream.set_callback = out_set_callback;
3539 out->stream.pause = out_pause;
3540 out->stream.resume = out_resume;
3541 out->stream.drain = out_drain;
3542 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07003543 out->usecase = get_offload_usecase(adev, false);
3544 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07003545 }
vivek mehta446c3962015-09-14 10:57:35 -07003546
3547 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08003548 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3549 config->format == 0 && config->sample_rate == 0 &&
3550 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07003551 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08003552 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3553 } else {
3554 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
3555 ret = -EEXIST;
3556 goto error_open;
3557 }
vivek mehta446c3962015-09-14 10:57:35 -07003558 }
3559
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003560 if (config->offload_info.channel_mask)
3561 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003562 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08003564 config->offload_info.channel_mask = config->channel_mask;
3565 }
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003566 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003567 out->sample_rate = config->offload_info.sample_rate;
3568
Mingming Yin3ee55c62014-08-04 14:23:35 -07003569 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003570
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303571 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
3572 if (audio_extn_is_dolby_format(config->offload_info.format)) {
3573 audio_extn_dolby_send_ddp_endp_params(adev);
3574 audio_extn_dolby_set_dmid(adev);
3575 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003576
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003577 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08003578 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003579 out->compr_config.codec->bit_rate =
3580 config->offload_info.bit_rate;
3581 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05303582 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303584 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003585 /*TODO: Do we need to change it for passthrough */
3586 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003587
Manish Dewangana6fc5442015-08-24 20:30:31 +05303588 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
3589 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
3590 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
3591 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303592
3593 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
3594 AUDIO_FORMAT_PCM) {
3595
3596 /*Based on platform support, configure appropriate alsa format for corresponding
3597 *hal input format.
3598 */
3599 out->compr_config.codec->format = hal_format_to_alsa(
3600 config->offload_info.format);
3601
Ashish Jain83a6cc22016-06-28 14:34:17 +05303602 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05303603 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303604 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303605
3606 /*for direct PCM playback populate bit_width based on selected alsa format as
3607 *hal input format and alsa format might differ based on platform support.
3608 */
3609 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05303610 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303611
3612 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
3613
3614 /* Check if alsa session is configured with the same format as HAL input format,
3615 * if not then derive correct fragment size needed to accomodate the
3616 * conversion of HAL input format to alsa format.
3617 */
3618 audio_extn_utils_update_direct_pcm_fragment_size(out);
3619
3620 /*if hal input and output fragment size is different this indicates HAL input format is
3621 *not same as the alsa format
3622 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303623 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303624 /*Allocate a buffer to convert input data to the alsa configured format.
3625 *size of convert buffer is equal to the size required to hold one fragment size
3626 *worth of pcm data, this is because flinger does not write more than fragment_size
3627 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05303628 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
3629 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05303630 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
3631 ret = -ENOMEM;
3632 goto error_open;
3633 }
3634 }
3635 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
3636 out->compr_config.fragment_size =
3637 audio_extn_passthru_get_buffer_size(&config->offload_info);
3638 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3639 } else {
3640 out->compr_config.fragment_size =
3641 platform_get_compress_offload_buffer_size(&config->offload_info);
3642 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3643 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07003644
Amit Shekhar6f461b12014-08-01 14:52:58 -07003645 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05303646 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003648 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3649 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003650
Alexy Josephaa54c872014-12-03 02:46:47 -08003651
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003652 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303653 out->send_next_track_params = false;
3654 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003655 out->offload_state = OFFLOAD_STATE_IDLE;
3656 out->playback_started = 0;
3657
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003658 audio_extn_dts_create_state_notifier_node(out->usecase);
3659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660 create_offload_callback_thread(out);
3661 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3662 __func__, config->offload_info.version,
3663 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05303664
3665 /* Disable gapless if any of the following is true
3666 * passthrough playback
3667 * AV playback
3668 * Direct PCM playback
3669 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303670 if (audio_extn_passthru_is_passthrough_stream(out) ||
Ashish Jain5106d362016-05-11 19:23:33 +05303671 config->offload_info.has_video ||
3672 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
3673 check_and_set_gapless_mode(adev, false);
3674 } else
3675 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07003676
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303677 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07003678 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
3679 }
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003680 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303681 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003682 if (ret != 0) {
3683 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3684 __func__, ret);
3685 goto error_open;
3686 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003687 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
3688 if (config->sample_rate == 0)
3689 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3690 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3691 config->sample_rate != 8000) {
3692 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3693 ret = -EINVAL;
3694 goto error_open;
3695 }
3696 out->sample_rate = config->sample_rate;
3697 out->config.rate = config->sample_rate;
3698 if (config->format == AUDIO_FORMAT_DEFAULT)
3699 config->format = AUDIO_FORMAT_PCM_16_BIT;
3700 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3701 config->format = AUDIO_FORMAT_PCM_16_BIT;
3702 ret = -EINVAL;
3703 goto error_open;
3704 }
3705 out->format = config->format;
3706 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3707 out->config = pcm_config_afe_proxy_playback;
3708 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003709 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303710 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3711 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003712 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
3713 out->flags);
3714 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303715 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3716 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3717 out->config = pcm_config_low_latency;
3718 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3719 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3720 out->config = pcm_config_deep_buffer;
3721 } else {
3722 /* primary path is the default path selected if no other outputs are available/suitable */
3723 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3724 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
3725 }
3726 out->hal_ip_format = format = out->format;
3727 out->config.format = hal_format_to_pcm(out->hal_ip_format);
3728 out->hal_op_format = pcm_format_to_hal(out->config.format);
3729 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
3730 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003731 out->sample_rate = out->config.rate;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303732 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
3733 if (out->hal_ip_format != out->hal_op_format) {
3734 uint32_t buffer_size = out->config.period_size *
3735 format_to_bitwidth_table[out->hal_op_format] *
3736 out->config.channels;
3737 out->convert_buffer = calloc(1, buffer_size);
3738 if (out->convert_buffer == NULL){
3739 ALOGE("Allocation failed for convert buffer for size %d",
3740 out->compr_config.fragment_size);
3741 ret = -ENOMEM;
3742 goto error_open;
3743 }
3744 ALOGD("Convert buffer allocated of size %d", buffer_size);
3745 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 }
3747
Ashish Jain83a6cc22016-06-28 14:34:17 +05303748 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags:%x",
3749 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags);
3750
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003751 /* TODO remove this hardcoding and check why width is zero*/
3752 if (out->bit_width == 0)
3753 out->bit_width = 16;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003754 audio_extn_utils_update_stream_app_type_cfg(adev->platform,
3755 &adev->streams_output_cfg_list,
Amit Shekhar1d896042014-10-03 13:16:09 -07003756 devices, flags, format, out->sample_rate,
Manish Dewangan837dc462015-05-27 10:17:41 +05303757 out->bit_width, out->channel_mask,
3758 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003759 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
3760 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
3761 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003762 if(adev->primary_output == NULL)
3763 adev->primary_output = out;
3764 else {
3765 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003766 ret = -EEXIST;
3767 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003768 }
3769 }
3770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 /* Check if this usecase is already existing */
3772 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07003773 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3774 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003777 ret = -EEXIST;
3778 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 }
3780 pthread_mutex_unlock(&adev->lock);
3781
3782 out->stream.common.get_sample_rate = out_get_sample_rate;
3783 out->stream.common.set_sample_rate = out_set_sample_rate;
3784 out->stream.common.get_buffer_size = out_get_buffer_size;
3785 out->stream.common.get_channels = out_get_channels;
3786 out->stream.common.get_format = out_get_format;
3787 out->stream.common.set_format = out_set_format;
3788 out->stream.common.standby = out_standby;
3789 out->stream.common.dump = out_dump;
3790 out->stream.common.set_parameters = out_set_parameters;
3791 out->stream.common.get_parameters = out_get_parameters;
3792 out->stream.common.add_audio_effect = out_add_audio_effect;
3793 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3794 out->stream.get_latency = out_get_latency;
3795 out->stream.set_volume = out_set_volume;
3796 out->stream.write = out_write;
3797 out->stream.get_render_position = out_get_render_position;
3798 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003799 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003801 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003803 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003804 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
3806 config->format = out->stream.common.get_format(&out->stream.common);
3807 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3808 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3809
3810 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303811 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07003812 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003813
3814 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3815 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3816 popcount(out->channel_mask), out->playback_started);
3817
Eric Laurent994a6932013-07-17 11:51:42 -07003818 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003820
3821error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05303822 if (out->convert_buffer)
3823 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003824 free(out);
3825 *stream_out = NULL;
3826 ALOGD("%s: exit: ret %d", __func__, ret);
3827 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828}
3829
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003830static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831 struct audio_stream_out *stream)
3832{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003833 struct stream_out *out = (struct stream_out *)stream;
3834 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003835 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303837 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3838
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003839 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303840 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003841 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303842 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003843 if(ret != 0)
3844 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3845 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003846 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003847 out_standby(&stream->common);
3848
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003849 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003850 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003851 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003852 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853 if (out->compr_config.codec != NULL)
3854 free(out->compr_config.codec);
3855 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003856
Ashish Jain83a6cc22016-06-28 14:34:17 +05303857 if (out->convert_buffer != NULL) {
3858 free(out->convert_buffer);
3859 out->convert_buffer = NULL;
3860 }
3861
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003862 if (adev->voice_tx_output == out)
3863 adev->voice_tx_output = NULL;
3864
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003865 pthread_cond_destroy(&out->cond);
3866 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003868 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869}
3870
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003871static void close_compress_sessions(struct audio_device *adev)
3872{
Mingming Yin7b762e72015-03-04 13:47:32 -08003873 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303874 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08003875 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003876 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303877
3878 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003879 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303880 if (is_offload_usecase(usecase->id)) {
3881 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003882 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3883 out = usecase->stream.out;
3884 pthread_mutex_unlock(&adev->lock);
3885 out_standby(&out->stream.common);
3886 pthread_mutex_lock(&adev->lock);
3887 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05303888 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07003889 }
3890 pthread_mutex_unlock(&adev->lock);
3891}
3892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3894{
3895 struct audio_device *adev = (struct audio_device *)dev;
3896 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003898 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003899 int ret;
3900 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003902 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303905 if (!parms)
3906 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003907 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3908 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05303909 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303910 if (strstr(snd_card_status, "OFFLINE")) {
3911 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303912 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08003913 //close compress sessions on OFFLINE status
3914 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303915 } else if (strstr(snd_card_status, "ONLINE")) {
3916 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05303917 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07003918 //send dts hpx license if enabled
3919 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05303920 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303921 }
3922
3923 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003924 status = voice_set_parameters(adev, parms);
3925 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003926 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003928 status = platform_set_parameters(adev->platform, parms);
3929 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003930 goto done;
3931
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003932 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3933 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07003934 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3936 adev->bluetooth_nrec = true;
3937 else
3938 adev->bluetooth_nrec = false;
3939 }
3940
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003941 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3942 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3944 adev->screen_off = false;
3945 else
3946 adev->screen_off = true;
3947 }
3948
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003949 ret = str_parms_get_int(parms, "rotation", &val);
3950 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003951 bool reverse_speakers = false;
3952 switch(val) {
3953 // FIXME: note that the code below assumes that the speakers are in the correct placement
3954 // relative to the user when the device is rotated 90deg from its default rotation. This
3955 // assumption is device-specific, not platform-specific like this code.
3956 case 270:
3957 reverse_speakers = true;
3958 break;
3959 case 0:
3960 case 90:
3961 case 180:
3962 break;
3963 default:
3964 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003965 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003966 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003967 if (status == 0) {
3968 if (adev->speaker_lr_swap != reverse_speakers) {
3969 adev->speaker_lr_swap = reverse_speakers;
3970 // only update the selected device if there is active pcm playback
3971 struct audio_usecase *usecase;
3972 struct listnode *node;
3973 list_for_each(node, &adev->usecase_list) {
3974 usecase = node_to_item(node, struct audio_usecase, list);
3975 if (usecase->type == PCM_PLAYBACK) {
3976 select_devices(adev, usecase->id);
3977 break;
3978 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003979 }
3980 }
3981 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003982 }
3983
Mingming Yin514a8bc2014-07-29 15:22:21 -07003984 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3985 if (ret >= 0) {
3986 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3987 adev->bt_wb_speech_enabled = true;
3988 else
3989 adev->bt_wb_speech_enabled = false;
3990 }
3991
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003992 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3993 if (ret >= 0) {
3994 val = atoi(value);
3995 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3996 ALOGV("cache new edid");
3997 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08003998 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
3999 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004000 /*
4001 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4002 * Per AudioPolicyManager, USB device is higher priority than WFD.
4003 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4004 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4005 * starting voice call on USB
4006 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004007 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4008 if (ret >= 0) {
4009 audio_extn_usb_add_device(val, atoi(value));
4010 }
vivek mehta344576a2016-04-12 18:56:03 -07004011 ALOGV("detected USB connect .. disable proxy");
4012 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004013 }
4014 }
4015
4016 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4017 if (ret >= 0) {
4018 val = atoi(value);
4019 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
4020 ALOGV("invalidate cached edid");
Mingming Yinddd610b2016-01-20 17:09:32 -08004021 platform_invalidate_hdmi_config(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004022 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
4023 (val & AUDIO_DEVICE_IN_USB_DEVICE)) {
4024 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4025 if (ret >= 0) {
4026 audio_extn_usb_remove_device(val, atoi(value));
4027 }
vivek mehta344576a2016-04-12 18:56:03 -07004028 ALOGV("detected USB disconnect .. enable proxy");
4029 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004030 }
4031 }
4032
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07004033 audio_extn_set_parameters(adev, parms);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304034 // reconfigure should be done only after updating a2dpstate in audio extn
4035 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4036 if (ret >= 0) {
4037 struct audio_usecase *usecase;
4038 struct listnode *node;
4039 list_for_each(node, &adev->usecase_list) {
4040 usecase = node_to_item(node, struct audio_usecase, list);
4041 if ((usecase->type == PCM_PLAYBACK) &&
4042 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)){
4043 ALOGD("reconfigure a2dp... forcing device switch");
4044 //force device switch to re configure encoder
4045 select_devices(adev, usecase->id);
4046 break;
4047 }
4048 }
4049 }
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004050
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004051done:
4052 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004053 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304054error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004055 ALOGV("%s: exit with code(%d)", __func__, status);
4056 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057}
4058
4059static char* adev_get_parameters(const struct audio_hw_device *dev,
4060 const char *keys)
4061{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004062 struct audio_device *adev = (struct audio_device *)dev;
4063 struct str_parms *reply = str_parms_create();
4064 struct str_parms *query = str_parms_create_str(keys);
4065 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304066 char value[256] = {0};
4067 int ret = 0;
4068
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004069 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004070 if (reply) {
4071 str_parms_destroy(reply);
4072 }
4073 if (query) {
4074 str_parms_destroy(query);
4075 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004076 ALOGE("adev_get_parameters: failed to create query or reply");
4077 return NULL;
4078 }
4079
Naresh Tannirud7205b62014-06-20 02:54:48 +05304080 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4081 sizeof(value));
4082 if (ret >=0) {
4083 int val = 1;
4084 pthread_mutex_lock(&adev->snd_card_status.lock);
4085 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4086 val = 0;
4087 pthread_mutex_unlock(&adev->snd_card_status.lock);
4088 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4089 goto exit;
4090 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004091
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004092 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004093 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004094 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004095 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304096 pthread_mutex_unlock(&adev->lock);
4097
Naresh Tannirud7205b62014-06-20 02:54:48 +05304098exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004099 str = str_parms_to_str(reply);
4100 str_parms_destroy(query);
4101 str_parms_destroy(reply);
4102
4103 ALOGV("%s: exit: returns - %s", __func__, str);
4104 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105}
4106
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004107static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108{
4109 return 0;
4110}
4111
4112static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4113{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004114 int ret;
4115 struct audio_device *adev = (struct audio_device *)dev;
4116 pthread_mutex_lock(&adev->lock);
4117 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004118 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004119 pthread_mutex_unlock(&adev->lock);
4120 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121}
4122
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004123static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4124 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125{
4126 return -ENOSYS;
4127}
4128
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004129static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4130 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131{
4132 return -ENOSYS;
4133}
4134
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004135static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4136 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137{
4138 return -ENOSYS;
4139}
4140
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004141static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4142 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143{
4144 return -ENOSYS;
4145}
4146
4147static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4148{
4149 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151 pthread_mutex_lock(&adev->lock);
4152 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004153 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004155 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004156 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004157 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004158 adev->current_call_output = NULL;
4159 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004160 }
4161 pthread_mutex_unlock(&adev->lock);
4162 return 0;
4163}
4164
4165static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4166{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004167 int ret;
4168
4169 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004170 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004171 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4172 pthread_mutex_unlock(&adev->lock);
4173
4174 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175}
4176
4177static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4178{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004179 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 return 0;
4181}
4182
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004183static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 const struct audio_config *config)
4185{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004186 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004188 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4189 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190}
4191
4192static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004193 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 audio_devices_t devices,
4195 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004196 struct audio_stream_in **stream_in,
4197 audio_input_flags_t flags __unused,
4198 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004199 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200{
4201 struct audio_device *adev = (struct audio_device *)dev;
4202 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004203 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004204 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004205 bool is_low_latency = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304208 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4209 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304211 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212
4213 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004214
4215 if (!in) {
4216 ALOGE("failed to allocate input stream");
4217 return -ENOMEM;
4218 }
4219
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304220 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304221 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4222 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004223 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004224 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 in->stream.common.get_sample_rate = in_get_sample_rate;
4227 in->stream.common.set_sample_rate = in_set_sample_rate;
4228 in->stream.common.get_buffer_size = in_get_buffer_size;
4229 in->stream.common.get_channels = in_get_channels;
4230 in->stream.common.get_format = in_get_format;
4231 in->stream.common.set_format = in_set_format;
4232 in->stream.common.standby = in_standby;
4233 in->stream.common.dump = in_dump;
4234 in->stream.common.set_parameters = in_set_parameters;
4235 in->stream.common.get_parameters = in_get_parameters;
4236 in->stream.common.add_audio_effect = in_add_audio_effect;
4237 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4238 in->stream.set_gain = in_set_gain;
4239 in->stream.read = in_read;
4240 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4241
4242 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004243 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004244 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 in->standby = 1;
4246 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004247 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004248 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249
4250 /* Update config params with the requested sample rate and channels */
4251 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004252 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4253 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4254 is_low_latency = true;
4255#if LOW_LATENCY_CAPTURE_USE_CASE
4256 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4257#endif
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004258 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004259 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004260
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004261 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004262 if (in->realtime) {
4263 in->config = pcm_config_audio_capture_rt;
4264 in->sample_rate = in->config.rate;
4265 in->af_period_multiplier = af_period_multiplier;
4266 } else {
4267 in->config = pcm_config_audio_capture;
4268 in->config.rate = config->sample_rate;
4269 in->sample_rate = config->sample_rate;
4270 in->af_period_multiplier = 1;
4271 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304272 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004274 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkalac862f712014-12-17 16:45:10 +05304275 if (adev->mode != AUDIO_MODE_IN_CALL) {
4276 ret = -EINVAL;
4277 goto err_open;
4278 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004279 if (config->sample_rate == 0)
4280 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4281 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4282 config->sample_rate != 8000) {
4283 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4284 ret = -EINVAL;
4285 goto err_open;
4286 }
4287 if (config->format == AUDIO_FORMAT_DEFAULT)
4288 config->format = AUDIO_FORMAT_PCM_16_BIT;
4289 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4290 config->format = AUDIO_FORMAT_PCM_16_BIT;
4291 ret = -EINVAL;
4292 goto err_open;
4293 }
4294
4295 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4296 in->config = pcm_config_afe_proxy_record;
4297 in->config.channels = channel_count;
4298 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304299 in->sample_rate = config->sample_rate;
Naresh Tanniruc9093982015-10-16 18:05:29 +05304300 } else if (!audio_extn_ssr_check_and_set_usecase(in)) {
4301 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004302 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004303 audio_extn_compr_cap_format_supported(config->format) &&
4304 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004305 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004306 } else {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304307 /* restrict 24 bit capture for unprocessed source only
4308 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4309 */
4310 if (config->format == AUDIO_FORMAT_DEFAULT) {
4311 config->format = AUDIO_FORMAT_PCM_16_BIT;
4312 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4313 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4314 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4315 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4316 bool ret_error = false;
4317 in->bit_width = 24;
4318 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4319 from HAL is 24_packed and 8_24
4320 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4321 24_packed return error indicating supported format is 24_packed
4322 *> In case of any other source requesting 24 bit or float return error
4323 indicating format supported is 16 bit only.
4324
4325 on error flinger will retry with supported format passed
4326 */
4327 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4328 (source != AUDIO_SOURCE_CAMCORDER)) {
4329 config->format = AUDIO_FORMAT_PCM_16_BIT;
4330 if( config->sample_rate > 48000)
4331 config->sample_rate = 48000;
4332 ret_error = true;
4333 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4334 in->config.format = PCM_FORMAT_S24_3LE;
4335 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4336 in->config.format = PCM_FORMAT_S24_LE;
4337 } else {
4338 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4339 ret_error = true;
4340 }
4341
4342 if (ret_error) {
4343 ret = -EINVAL;
4344 goto err_open;
4345 }
4346 }
4347
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004348 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004349 if (!in->realtime) {
4350 in->format = config->format;
4351 frame_size = audio_stream_in_frame_size(&in->stream);
4352 buffer_size = get_input_buffer_size(config->sample_rate,
4353 config->format,
4354 channel_count,
4355 is_low_latency);
4356 in->config.period_size = buffer_size / frame_size;
4357 }
4358
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004359 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4360 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4361 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004362 (in->config.rate == 8000 || in->config.rate == 16000 ||
4363 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004364 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4365 voice_extn_compress_voip_open_input_stream(in);
4366 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004367 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004369 /* This stream could be for sound trigger lab,
4370 get sound trigger pcm if present */
4371 audio_extn_sound_trigger_check_and_get_session(in);
4372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004374 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004375 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376
4377err_open:
4378 free(in);
4379 *stream_in = NULL;
4380 return ret;
4381}
4382
4383static void adev_close_input_stream(struct audio_hw_device *dev,
4384 struct audio_stream_in *stream)
4385{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004386 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004387 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004388 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304389
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304390 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004391
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304392 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07004393 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05304394
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004395 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304396 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004397 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304398 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004399 if (ret != 0)
4400 ALOGE("%s: Compress voip input cannot be closed, error:%d",
4401 __func__, ret);
4402 } else
4403 in_standby(&stream->common);
4404
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07004405 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004406 audio_extn_ssr_deinit();
4407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408
Mingming Yine62d7842013-10-25 16:26:03 -07004409 if(audio_extn_compr_cap_enabled() &&
4410 audio_extn_compr_cap_format_supported(in->config.format))
4411 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004412
Mingming Yinfd7607b2016-01-22 12:48:44 -08004413 if (in->is_st_session) {
4414 ALOGV("%s: sound trigger pcm stop lab", __func__);
4415 audio_extn_sound_trigger_stop_lab(in);
4416 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004417 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418 return;
4419}
4420
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004421static int adev_dump(const audio_hw_device_t *device __unused,
4422 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423{
4424 return 0;
4425}
4426
4427static int adev_close(hw_device_t *device)
4428{
4429 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07004430
4431 if (!adev)
4432 return 0;
4433
4434 pthread_mutex_lock(&adev_init_lock);
4435
4436 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004437 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08004438 audio_extn_listen_deinit(adev);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004439 audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
Kiran Kandi910e1862013-10-29 13:29:42 -07004440 audio_route_free(adev->audio_route);
4441 free(adev->snd_dev_ref_cnt);
4442 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004443 if (adev->adm_deinit)
4444 adev->adm_deinit(adev->adm_data);
Kiran Kandi910e1862013-10-29 13:29:42 -07004445 free(device);
4446 adev = NULL;
4447 }
4448 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450 return 0;
4451}
4452
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004453/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4454 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4455 * just that it _might_ work.
4456 */
4457static int period_size_is_plausible_for_low_latency(int period_size)
4458{
4459 switch (period_size) {
4460 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07004461 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004462 case 240:
4463 case 320:
4464 case 480:
4465 return 1;
4466 default:
4467 return 0;
4468 }
4469}
4470
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471static int adev_open(const hw_module_t *module, const char *name,
4472 hw_device_t **device)
4473{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004474 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4476
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004477 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07004478 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004479 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07004480 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004481 ALOGD("%s: returning existing instance of adev", __func__);
4482 ALOGD("%s: exit", __func__);
4483 pthread_mutex_unlock(&adev_init_lock);
4484 return 0;
4485 }
4486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004487 adev = calloc(1, sizeof(struct audio_device));
4488
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004489 if (!adev) {
4490 pthread_mutex_unlock(&adev_init_lock);
4491 return -ENOMEM;
4492 }
4493
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004494 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4497 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4498 adev->device.common.module = (struct hw_module_t *)module;
4499 adev->device.common.close = adev_close;
4500
4501 adev->device.init_check = adev_init_check;
4502 adev->device.set_voice_volume = adev_set_voice_volume;
4503 adev->device.set_master_volume = adev_set_master_volume;
4504 adev->device.get_master_volume = adev_get_master_volume;
4505 adev->device.set_master_mute = adev_set_master_mute;
4506 adev->device.get_master_mute = adev_get_master_mute;
4507 adev->device.set_mode = adev_set_mode;
4508 adev->device.set_mic_mute = adev_set_mic_mute;
4509 adev->device.get_mic_mute = adev_get_mic_mute;
4510 adev->device.set_parameters = adev_set_parameters;
4511 adev->device.get_parameters = adev_get_parameters;
4512 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4513 adev->device.open_output_stream = adev_open_output_stream;
4514 adev->device.close_output_stream = adev_close_output_stream;
4515 adev->device.open_input_stream = adev_open_input_stream;
4516 adev->device.close_input_stream = adev_close_input_stream;
4517 adev->device.dump = adev_dump;
4518
4519 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004521 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004522 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004524 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004525 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07004526 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004527 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004528 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004529 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004530 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08004531 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004532 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05304533 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304534 adev->perf_lock_opts[0] = 0x101;
4535 adev->perf_lock_opts[1] = 0x20E;
4536 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304537
4538 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
4539 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004541 adev->platform = platform_init(adev);
4542 if (!adev->platform) {
4543 free(adev->snd_dev_ref_cnt);
4544 free(adev);
4545 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4546 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08004547 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004548 return -EINVAL;
4549 }
Eric Laurentc4aef752013-09-12 17:45:53 -07004550
Naresh Tanniru4c630392014-05-12 01:05:52 +05304551 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
4552
Eric Laurentc4aef752013-09-12 17:45:53 -07004553 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
4554 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4555 if (adev->visualizer_lib == NULL) {
4556 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4557 } else {
4558 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4559 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004560 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07004561 "visualizer_hal_start_output");
4562 adev->visualizer_stop_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_stop_output");
4565 }
4566 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08004567 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004568 audio_extn_sound_trigger_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07004569
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004570 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
4571 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4572 if (adev->offload_effects_lib == NULL) {
4573 ALOGE("%s: DLOPEN failed for %s", __func__,
4574 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4575 } else {
4576 ALOGV("%s: DLOPEN successful for %s", __func__,
4577 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4578 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05304579 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004580 "offload_effects_bundle_hal_start_output");
4581 adev->offload_effects_stop_output =
4582 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4583 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004584 adev->offload_effects_set_hpx_state =
4585 (int (*)(bool))dlsym(adev->offload_effects_lib,
4586 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05304587 adev->offload_effects_get_parameters =
4588 (void (*)(struct str_parms *, struct str_parms *))
4589 dlsym(adev->offload_effects_lib,
4590 "offload_effects_bundle_get_parameters");
4591 adev->offload_effects_set_parameters =
4592 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
4593 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08004594 }
4595 }
4596
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004597 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
4598 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4599 if (adev->adm_lib == NULL) {
4600 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4601 } else {
4602 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4603 adev->adm_init = (adm_init_t)
4604 dlsym(adev->adm_lib, "adm_init");
4605 adev->adm_deinit = (adm_deinit_t)
4606 dlsym(adev->adm_lib, "adm_deinit");
4607 adev->adm_register_input_stream = (adm_register_input_stream_t)
4608 dlsym(adev->adm_lib, "adm_register_input_stream");
4609 adev->adm_register_output_stream = (adm_register_output_stream_t)
4610 dlsym(adev->adm_lib, "adm_register_output_stream");
4611 adev->adm_deregister_stream = (adm_deregister_stream_t)
4612 dlsym(adev->adm_lib, "adm_deregister_stream");
4613 adev->adm_request_focus = (adm_request_focus_t)
4614 dlsym(adev->adm_lib, "adm_request_focus");
4615 adev->adm_abandon_focus = (adm_abandon_focus_t)
4616 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004617 adev->adm_set_config = (adm_set_config_t)
4618 dlsym(adev->adm_lib, "adm_set_config");
4619 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4620 dlsym(adev->adm_lib, "adm_request_focus_v2");
4621 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4622 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4623 adev->adm_on_routing_change = (adm_on_routing_change_t)
4624 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004625 }
4626 }
4627
Mingming Yin514a8bc2014-07-29 15:22:21 -07004628 adev->bt_wb_speech_enabled = false;
4629
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07004630 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 *device = &adev->device.common;
4632
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004633 audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
4634 &adev->streams_output_cfg_list);
4635
Kiran Kandi910e1862013-10-29 13:29:42 -07004636 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004637
4638 char value[PROPERTY_VALUE_MAX];
4639 int trial;
4640 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4641 trial = atoi(value);
4642 if (period_size_is_plausible_for_low_latency(trial)) {
4643 pcm_config_low_latency.period_size = trial;
4644 pcm_config_low_latency.start_threshold = trial / 4;
4645 pcm_config_low_latency.avail_min = trial / 4;
4646 configured_low_latency_capture_period_size = trial;
4647 }
4648 }
4649 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4650 trial = atoi(value);
4651 if (period_size_is_plausible_for_low_latency(trial)) {
4652 configured_low_latency_capture_period_size = trial;
4653 }
4654 }
4655
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004656 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4657 af_period_multiplier = atoi(value);
4658 if (af_period_multiplier < 0)
4659 af_period_multiplier = 2;
4660 else if (af_period_multiplier > 4)
4661 af_period_multiplier = 4;
4662
4663 ALOGV("new period_multiplier = %d", af_period_multiplier);
4664 }
4665
vivek mehta446c3962015-09-14 10:57:35 -07004666 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004667 pthread_mutex_unlock(&adev_init_lock);
4668
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004669 if (adev->adm_init)
4670 adev->adm_data = adev->adm_init();
4671
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304672 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07004673 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 return 0;
4675}
4676
4677static struct hw_module_methods_t hal_module_methods = {
4678 .open = adev_open,
4679};
4680
4681struct audio_module HAL_MODULE_INFO_SYM = {
4682 .common = {
4683 .tag = HARDWARE_MODULE_TAG,
4684 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4685 .hal_api_version = HARDWARE_HAL_API_VERSION,
4686 .id = AUDIO_HARDWARE_MODULE_ID,
4687 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08004688 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689 .methods = &hal_module_methods,
4690 },
4691};