blob: df52b4ca18fca910cda122b12410f857132e932e [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, 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#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053083#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070085#define PROXY_OPEN_RETRY_COUNT 100
86#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080087
Mingming Yin08c7e312015-03-16 18:10:58 -070088#ifdef USE_LL_AS_PRIMARY_OUTPUT
89#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
90#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
91#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080092#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070093#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
94#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080095
Haynes Mathew George5beddd42016-06-27 18:33:40 -070096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurentb23d5282013-05-14 15:27:20 -0700101struct pcm_config pcm_config_deep_buffer = {
102 .channels = 2,
103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
104 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
105 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110};
111
112struct pcm_config pcm_config_low_latency = {
113 .channels = 2,
114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
116 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121};
122
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700123static int af_period_multiplier = 4;
124struct pcm_config pcm_config_rt = {
125 .channels = 2,
126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = ULL_PERIOD_SIZE, //1 ms
128 .period_count = 512, //=> buffer size is 512ms
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
131 .stop_threshold = INT_MAX,
132 .silence_threshold = 0,
133 .silence_size = 0,
134 .avail_min = ULL_PERIOD_SIZE, //1 ms
135};
136
Eric Laurentb23d5282013-05-14 15:27:20 -0700137struct pcm_config pcm_config_hdmi_multi = {
138 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
139 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
140 .period_size = HDMI_MULTI_PERIOD_SIZE,
141 .period_count = HDMI_MULTI_PERIOD_COUNT,
142 .format = PCM_FORMAT_S16_LE,
143 .start_threshold = 0,
144 .stop_threshold = INT_MAX,
145 .avail_min = 0,
146};
147
148struct pcm_config pcm_config_audio_capture = {
149 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700150 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
151 .format = PCM_FORMAT_S16_LE,
152};
153
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700154struct pcm_config pcm_config_audio_capture_rt = {
155 .channels = 2,
156 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
157 .period_size = ULL_PERIOD_SIZE,
158 .period_count = 512,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = 0,
161 .stop_threshold = INT_MAX,
162 .silence_threshold = 0,
163 .silence_size = 0,
164 .avail_min = ULL_PERIOD_SIZE, //1 ms
165};
166
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700167#define AFE_PROXY_CHANNEL_COUNT 2
168#define AFE_PROXY_SAMPLING_RATE 48000
169
170#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
171#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
172
173struct pcm_config pcm_config_afe_proxy_playback = {
174 .channels = AFE_PROXY_CHANNEL_COUNT,
175 .rate = AFE_PROXY_SAMPLING_RATE,
176 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
177 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
178 .format = PCM_FORMAT_S16_LE,
179 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
180 .stop_threshold = INT_MAX,
181 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182};
183
184#define AFE_PROXY_RECORD_PERIOD_SIZE 768
185#define AFE_PROXY_RECORD_PERIOD_COUNT 4
186
187struct pcm_config pcm_config_afe_proxy_record = {
188 .channels = AFE_PROXY_CHANNEL_COUNT,
189 .rate = AFE_PROXY_SAMPLING_RATE,
190 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
191 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
194 .stop_threshold = INT_MAX,
195 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
196};
197
Ashish Jainf1eaa582016-05-23 20:54:24 +0530198#define AUDIO_MAX_PCM_FORMATS 7
199
200const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
201 [AUDIO_FORMAT_DEFAULT] = 0,
202 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
203 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
204 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
205 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
206 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
207 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
208};
209
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800210const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700211 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
212 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700213 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
214 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700215 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700216 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
218 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
219 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700225
Eric Laurentb23d5282013-05-14 15:27:20 -0700226 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700227 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530228 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
229 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
230 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700231 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700232 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700233 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800234 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800235 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700236 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700237
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE2_CALL] = "voice2-call",
239 [USECASE_VOLTE_CALL] = "volte-call",
240 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800241 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800242 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
243 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800244 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700245 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
246 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
247 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800248 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
249 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
250 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
251
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700252 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
253 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700254 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
255 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700256
257 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
258 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700259 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700260};
261
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700262static const audio_usecase_t offload_usecases[] = {
263 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700272};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800273
274#define STRING_TO_ENUM(string) { #string, string }
275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800276struct string_to_enum {
277 const char *name;
278 uint32_t value;
279};
280
281static const struct string_to_enum out_channels_name_to_enum_table[] = {
282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
290};
291
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700292static const struct string_to_enum out_formats_name_to_enum_table[] = {
293 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
295 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800296 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
297 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
298};
299
300//list of all supported sample rates by HDMI specification.
301static const int out_hdmi_sample_rates[] = {
302 32000, 44100, 48000, 88200, 96000, 176400, 192000,
303};
304
305static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
306 STRING_TO_ENUM(32000),
307 STRING_TO_ENUM(44100),
308 STRING_TO_ENUM(48000),
309 STRING_TO_ENUM(88200),
310 STRING_TO_ENUM(96000),
311 STRING_TO_ENUM(176400),
312 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700313};
314
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700315static struct audio_device *adev = NULL;
316static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700317static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700318//cache last MBDRC cal step level
319static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700320
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700321static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
322 int flags __unused)
323{
324 int dir = 0;
325 switch (uc_id) {
326 case USECASE_AUDIO_RECORD_LOW_LATENCY:
327 dir = 1;
328 case USECASE_AUDIO_PLAYBACK_ULL:
329 break;
330 default:
331 return false;
332 }
333
334 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
335 PCM_PLAYBACK : PCM_CAPTURE);
336 if (adev->adm_is_noirq_avail)
337 return adev->adm_is_noirq_avail(adev->adm_data,
338 adev->snd_card, dev_id, dir);
339 return false;
340}
341
342static void register_out_stream(struct stream_out *out)
343{
344 struct audio_device *adev = out->dev;
345 if (is_offload_usecase(out->usecase) ||
346 !adev->adm_register_output_stream)
347 return;
348
349 // register stream first for backward compatibility
350 adev->adm_register_output_stream(adev->adm_data,
351 out->handle,
352 out->flags);
353
354 if (!adev->adm_set_config)
355 return;
356
357 if (out->realtime)
358 adev->adm_set_config(adev->adm_data,
359 out->handle,
360 out->pcm, &out->config);
361}
362
363static void register_in_stream(struct stream_in *in)
364{
365 struct audio_device *adev = in->dev;
366 if (!adev->adm_register_input_stream)
367 return;
368
369 adev->adm_register_input_stream(adev->adm_data,
370 in->capture_handle,
371 in->flags);
372
373 if (!adev->adm_set_config)
374 return;
375
376 if (in->realtime)
377 adev->adm_set_config(adev->adm_data,
378 in->capture_handle,
379 in->pcm,
380 &in->config);
381}
382
383static void request_out_focus(struct stream_out *out, long ns)
384{
385 struct audio_device *adev = out->dev;
386
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700387 if (adev->adm_request_focus_v2)
388 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
389 else if (adev->adm_request_focus)
390 adev->adm_request_focus(adev->adm_data, out->handle);
391}
392
393static void request_in_focus(struct stream_in *in, long ns)
394{
395 struct audio_device *adev = in->dev;
396
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700397 if (adev->adm_request_focus_v2)
398 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
399 else if (adev->adm_request_focus)
400 adev->adm_request_focus(adev->adm_data, in->capture_handle);
401}
402
403static void release_out_focus(struct stream_out *out)
404{
405 struct audio_device *adev = out->dev;
406
407 if (adev->adm_abandon_focus)
408 adev->adm_abandon_focus(adev->adm_data, out->handle);
409}
410
411static void release_in_focus(struct stream_in *in)
412{
413 struct audio_device *adev = in->dev;
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
416}
417
vivek mehtaa76401a2015-04-24 14:12:15 -0700418__attribute__ ((visibility ("default")))
419bool audio_hw_send_gain_dep_calibration(int level) {
420 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700421 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700422
423 pthread_mutex_lock(&adev_init_lock);
424
425 if (adev != NULL && adev->platform != NULL) {
426 pthread_mutex_lock(&adev->lock);
427 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700428
429 // if cal set fails, cache level info
430 // if cal set succeds, reset known last cal set
431 if (!ret_val)
432 last_known_cal_step = level;
433 else if (last_known_cal_step != -1)
434 last_known_cal_step = -1;
435
vivek mehtaa76401a2015-04-24 14:12:15 -0700436 pthread_mutex_unlock(&adev->lock);
437 } else {
438 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
439 }
440
441 pthread_mutex_unlock(&adev_init_lock);
442
443 return ret_val;
444}
445
Ashish Jain5106d362016-05-11 19:23:33 +0530446static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
447{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800448 bool gapless_enabled = false;
449 const char *mixer_ctl_name = "Compress Gapless Playback";
450 struct mixer_ctl *ctl;
451
452 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530453 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
454
455 /*Disable gapless if its AV playback*/
456 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800457
458 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
459 if (!ctl) {
460 ALOGE("%s: Could not get ctl for mixer cmd - %s",
461 __func__, mixer_ctl_name);
462 return -EINVAL;
463 }
464
465 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
466 ALOGE("%s: Could not set gapless mode %d",
467 __func__, gapless_enabled);
468 return -EINVAL;
469 }
470 return 0;
471}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700472
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700473__attribute__ ((visibility ("default")))
474int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
475 int table_size) {
476 int ret_val = 0;
477 ALOGV("%s: enter ... ", __func__);
478
479 pthread_mutex_lock(&adev_init_lock);
480 if (adev == NULL) {
481 ALOGW("%s: adev is NULL .... ", __func__);
482 goto done;
483 }
484
485 pthread_mutex_lock(&adev->lock);
486 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
487 pthread_mutex_unlock(&adev->lock);
488done:
489 pthread_mutex_unlock(&adev_init_lock);
490 ALOGV("%s: exit ... ", __func__);
491 return ret_val;
492}
493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700494static bool is_supported_format(audio_format_t format)
495{
Eric Laurent86e17132013-09-12 17:49:30 -0700496 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530497 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530498 format == AUDIO_FORMAT_AAC_LC ||
499 format == AUDIO_FORMAT_AAC_HE_V1 ||
500 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530501 format == AUDIO_FORMAT_AAC_ADTS_LC ||
502 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
503 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530504 format == AUDIO_FORMAT_AAC_LATM_LC ||
505 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
506 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530507 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
508 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530509 format == AUDIO_FORMAT_PCM_FLOAT ||
510 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700511 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530512 format == AUDIO_FORMAT_AC3 ||
513 format == AUDIO_FORMAT_E_AC3 ||
514 format == AUDIO_FORMAT_DTS ||
515 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800516 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530517 format == AUDIO_FORMAT_ALAC ||
518 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530519 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530520 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800521 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530522 format == AUDIO_FORMAT_WMA_PRO ||
523 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800524 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525
526 return false;
527}
528
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700529static inline bool is_mmap_usecase(audio_usecase_t uc_id)
530{
531 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
532 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
533}
534
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530535int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530536{
537 int snd_scard_state;
538
539 if (!adev)
540 return SND_CARD_STATE_OFFLINE;
541
542 pthread_mutex_lock(&adev->snd_card_status.lock);
543 snd_scard_state = adev->snd_card_status.state;
544 pthread_mutex_unlock(&adev->snd_card_status.lock);
545
546 return snd_scard_state;
547}
548
549static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
550{
551 if (!adev)
552 return -ENOSYS;
553
554 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700555 if (adev->snd_card_status.state != snd_scard_state) {
556 adev->snd_card_status.state = snd_scard_state;
557 platform_snd_card_update(adev->platform, snd_scard_state);
558 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530559 pthread_mutex_unlock(&adev->snd_card_status.lock);
560
561 return 0;
562}
563
Avinash Vaish71a8b972014-07-24 15:36:33 +0530564static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
565 struct audio_usecase *uc_info)
566{
567 struct listnode *node;
568 struct audio_usecase *usecase;
569
570 if (uc_info == NULL)
571 return -EINVAL;
572
573 /* Re-route all voice usecases on the shared backend other than the
574 specified usecase to new snd devices */
575 list_for_each(node, &adev->usecase_list) {
576 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800577 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530578 enable_audio_route(adev, usecase);
579 }
580 return 0;
581}
582
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530583static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530584{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585 ALOGV("%s", __func__);
586 audio_route_apply_and_update_path(adev->audio_route,
587 "asrc-mode");
588 adev->asrc_mode_enabled = true;
589}
590
591static void disable_asrc_mode(struct audio_device *adev)
592{
593 ALOGV("%s", __func__);
594 audio_route_reset_and_update_path(adev->audio_route,
595 "asrc-mode");
596 adev->asrc_mode_enabled = false;
597}
598
599/*
600 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
601 * 44.1 or Native DSD backends are enabled for any of current use case.
602 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
603 * - Disable current mix path use case(Headphone backend) and re-enable it with
604 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
605 * e.g. Naitve DSD or Headphone 44.1 -> + 48
606 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530607static void check_and_set_asrc_mode(struct audio_device *adev,
608 struct audio_usecase *uc_info,
609 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530610{
611 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530612 int i, num_new_devices = 0;
613 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
614 /*
615 *Split snd device for new combo use case
616 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
617 */
618 if (platform_split_snd_device(adev->platform,
619 snd_device,
620 &num_new_devices,
621 split_new_snd_devices) == 0) {
622 for (i = 0; i < num_new_devices; i++)
623 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
624 } else {
625 int new_backend_idx = platform_get_backend_index(snd_device);
626 if (((new_backend_idx == HEADPHONE_BACKEND) ||
627 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
628 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
629 !adev->asrc_mode_enabled) {
630 struct listnode *node = NULL;
631 struct audio_usecase *uc = NULL;
632 struct stream_out *curr_out = NULL;
633 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
634 int i, num_devices, ret = 0;
635 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530636
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530637 list_for_each(node, &adev->usecase_list) {
638 uc = node_to_item(node, struct audio_usecase, list);
639 curr_out = (struct stream_out*) uc->stream.out;
640 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
641 /*
642 *Split snd device for existing combo use case
643 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
644 */
645 ret = platform_split_snd_device(adev->platform,
646 uc->out_snd_device,
647 &num_devices,
648 split_snd_devices);
649 if (ret < 0 || num_devices == 0) {
650 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
651 split_snd_devices[0] = uc->out_snd_device;
652 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800653 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530654 for (i = 0; i < num_devices; i++) {
655 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
656 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
657 if((new_backend_idx == HEADPHONE_BACKEND) &&
658 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
659 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
660 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
661 __func__);
662 enable_asrc_mode(adev);
663 break;
664 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
665 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
666 (usecase_backend_idx == HEADPHONE_BACKEND)) {
667 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
668 __func__);
669 disable_audio_route(adev, uc);
670 disable_snd_device(adev, uc->out_snd_device);
671 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
672 if (new_backend_idx == DSD_NATIVE_BACKEND)
673 audio_route_apply_and_update_path(adev->audio_route,
674 "hph-true-highquality-mode");
675 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
676 (curr_out->bit_width >= 24))
677 audio_route_apply_and_update_path(adev->audio_route,
678 "hph-highquality-mode");
679 enable_asrc_mode(adev);
680 enable_snd_device(adev, uc->out_snd_device);
681 enable_audio_route(adev, uc);
682 break;
683 }
684 }
685 // reset split devices count
686 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800687 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530688 if (adev->asrc_mode_enabled)
689 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530690 }
691 }
692 }
693}
694
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700695int pcm_ioctl(struct pcm *pcm, int request, ...)
696{
697 va_list ap;
698 void * arg;
699 int pcm_fd = *(int*)pcm;
700
701 va_start(ap, request);
702 arg = va_arg(ap, void *);
703 va_end(ap);
704
705 return ioctl(pcm_fd, request, arg);
706}
707
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700708int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800710{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700712 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800713
714 if (usecase == NULL)
715 return -EINVAL;
716
717 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
718
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800719 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800721 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800723
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800724#ifdef DS1_DOLBY_DAP_ENABLED
725 audio_extn_dolby_set_dmid(adev);
726 audio_extn_dolby_set_endpoint(adev);
727#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700728 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700729 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530730 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700731 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530732 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800733 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700734 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700735 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700736 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800737 ALOGV("%s: exit", __func__);
738 return 0;
739}
740
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700741int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700742 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700745 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800746
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530747 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800748 return -EINVAL;
749
750 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 if (usecase->type == PCM_CAPTURE)
752 snd_device = usecase->in_snd_device;
753 else
754 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800755 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700756 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700757 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700758 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700759 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530760 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800761 ALOGV("%s: exit", __func__);
762 return 0;
763}
764
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700765int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700766 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530768 int i, num_devices = 0;
769 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700770 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
771
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800772 if (snd_device < SND_DEVICE_MIN ||
773 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800774 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800775 return -EINVAL;
776 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777
778 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779
780 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
781 ALOGE("%s: Invalid sound device returned", __func__);
782 return -EINVAL;
783 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700784 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700785 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700786 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 return 0;
788 }
789
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530790
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700791 if (audio_extn_spkr_prot_is_enabled())
792 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700793
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800794 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
795 audio_extn_spkr_prot_is_enabled()) {
796 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700797 adev->snd_dev_ref_cnt[snd_device]--;
798 return -EINVAL;
799 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200800 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800801 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800802 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200803 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800804 return -EINVAL;
805 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700806 } else if (platform_split_snd_device(adev->platform,
807 snd_device,
808 &num_devices,
809 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530810 for (i = 0; i < num_devices; i++) {
811 enable_snd_device(adev, new_snd_devices[i]);
812 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800813 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700814 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530815
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530816
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530817 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
818 (audio_extn_a2dp_start_playback() < 0)) {
819 ALOGE(" fail to configure A2dp control path ");
820 return -EINVAL;
821 }
822
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700823 /* due to the possibility of calibration overwrite between listen
824 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700825 audio_extn_sound_trigger_update_device_status(snd_device,
826 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530827 audio_extn_listen_update_device_status(snd_device,
828 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700829 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700830 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700831 audio_extn_sound_trigger_update_device_status(snd_device,
832 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530833 audio_extn_listen_update_device_status(snd_device,
834 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700835 return -EINVAL;
836 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300837 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700838 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530839
840 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
841 !adev->native_playback_enabled &&
842 audio_is_true_native_stream_active(adev)) {
843 ALOGD("%s: %d: napb: enabling native mode in hardware",
844 __func__, __LINE__);
845 audio_route_apply_and_update_path(adev->audio_route,
846 "true-native-mode");
847 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530848 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850 return 0;
851}
852
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700853int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700854 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530856 int i, num_devices = 0;
857 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700858 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
859
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800860 if (snd_device < SND_DEVICE_MIN ||
861 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800862 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800863 return -EINVAL;
864 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
866 ALOGE("%s: device ref cnt is already 0", __func__);
867 return -EINVAL;
868 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700869
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700871
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700872 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
873 ALOGE("%s: Invalid sound device returned", __func__);
874 return -EINVAL;
875 }
876
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700878 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530879
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800880 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
881 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700882 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700883 } else if (platform_split_snd_device(adev->platform,
884 snd_device,
885 &num_devices,
886 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530887 for (i = 0; i < num_devices; i++) {
888 disable_snd_device(adev, new_snd_devices[i]);
889 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300890 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700891 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300892 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700893
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530894 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
895 audio_extn_a2dp_stop_playback();
896
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700897 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530898 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530899 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
900 adev->native_playback_enabled) {
901 ALOGD("%s: %d: napb: disabling native mode in hardware",
902 __func__, __LINE__);
903 audio_route_reset_and_update_path(adev->audio_route,
904 "true-native-mode");
905 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530906 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
907 adev->asrc_mode_enabled) {
908 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530909 disable_asrc_mode(adev);
910 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530911 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530912
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200913 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700914 audio_extn_sound_trigger_update_device_status(snd_device,
915 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530916 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800917 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700918 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800920 return 0;
921}
922
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700923/*
924 legend:
925 uc - existing usecase
926 new_uc - new usecase
927 d1, d11, d2 - SND_DEVICE enums
928 a1, a2 - corresponding ANDROID device enums
929 B1, B2 - backend strings
930
931case 1
932 uc->dev d1 (a1) B1
933 new_uc->dev d1 (a1), d2 (a2) B1, B2
934
935 resolution: disable and enable uc->dev on d1
936
937case 2
938 uc->dev d1 (a1) B1
939 new_uc->dev d11 (a1) B1
940
941 resolution: need to switch uc since d1 and d11 are related
942 (e.g. speaker and voice-speaker)
943 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
944
945case 3
946 uc->dev d1 (a1) B1
947 new_uc->dev d2 (a2) B2
948
949 resolution: no need to switch uc
950
951case 4
952 uc->dev d1 (a1) B1
953 new_uc->dev d2 (a2) B1
954
955 resolution: disable enable uc-dev on d2 since backends match
956 we cannot enable two streams on two different devices if they
957 share the same backend. e.g. if offload is on speaker device using
958 QUAD_MI2S backend and a low-latency stream is started on voice-handset
959 using the same backend, offload must also be switched to voice-handset.
960
961case 5
962 uc->dev d1 (a1) B1
963 new_uc->dev d1 (a1), d2 (a2) B1
964
965 resolution: disable enable uc-dev on d2 since backends match
966 we cannot enable two streams on two different devices if they
967 share the same backend.
968
969case 6
970 uc->dev d1 (a1) B1
971 new_uc->dev d2 (a1) B2
972
973 resolution: no need to switch
974
975case 7
976 uc->dev d1 (a1), d2 (a2) B1, B2
977 new_uc->dev d1 (a1) B1
978
979 resolution: no need to switch
980
981*/
982static snd_device_t derive_playback_snd_device(void * platform,
983 struct audio_usecase *uc,
984 struct audio_usecase *new_uc,
985 snd_device_t new_snd_device)
986{
987 audio_devices_t a1 = uc->stream.out->devices;
988 audio_devices_t a2 = new_uc->stream.out->devices;
989
990 snd_device_t d1 = uc->out_snd_device;
991 snd_device_t d2 = new_snd_device;
992
993 // Treat as a special case when a1 and a2 are not disjoint
994 if ((a1 != a2) && (a1 & a2)) {
995 snd_device_t d3[2];
996 int num_devices = 0;
997 int ret = platform_split_snd_device(platform,
998 popcount(a1) > 1 ? d1 : d2,
999 &num_devices,
1000 d3);
1001 if (ret < 0) {
1002 if (ret != -ENOSYS) {
1003 ALOGW("%s failed to split snd_device %d",
1004 __func__,
1005 popcount(a1) > 1 ? d1 : d2);
1006 }
1007 goto end;
1008 }
1009
1010 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1011 // But if it does happen, we need to give priority to d2 if
1012 // the combo devices active on the existing usecase share a backend.
1013 // This is because we cannot have a usecase active on a combo device
1014 // and a new usecase requests one device in this combo pair.
1015 if (platform_check_backends_match(d3[0], d3[1])) {
1016 return d2; // case 5
1017 } else {
1018 return d1; // case 1
1019 }
1020 } else {
1021 if (platform_check_backends_match(d1, d2)) {
1022 return d2; // case 2, 4
1023 } else {
1024 return d1; // case 6, 3
1025 }
1026 }
1027
1028end:
1029 return d2; // return whatever was calculated before.
1030}
1031
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301033 struct audio_usecase *uc_info,
1034 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001035{
1036 struct listnode *node;
1037 struct audio_usecase *usecase;
1038 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301039 snd_device_t uc_derive_snd_device;
1040 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001042 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301043 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044 /*
1045 * This function is to make sure that all the usecases that are active on
1046 * the hardware codec backend are always routed to any one device that is
1047 * handled by the hardware codec.
1048 * For example, if low-latency and deep-buffer usecases are currently active
1049 * on speaker and out_set_parameters(headset) is received on low-latency
1050 * output, then we have to make sure deep-buffer is also switched to headset,
1051 * because of the limitation that both the devices cannot be enabled
1052 * at the same time as they share the same backend.
1053 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001054 /*
1055 * This call is to check if we need to force routing for a particular stream
1056 * If there is a backend configuration change for the device when a
1057 * new stream starts, then ADM needs to be closed and re-opened with the new
1058 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001059 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001060 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001061 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1062 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301063 /* For a2dp device reconfigure all active sessions
1064 * with new AFE encoder format based on a2dp state
1065 */
1066 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1067 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1068 audio_extn_a2dp_is_force_device_switch()) {
1069 force_routing = true;
1070 force_restart_session = true;
1071 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301072 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1073
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001074 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001075 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001076 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1078 switch_device[i] = false;
1079
1080 list_for_each(node, &adev->usecase_list) {
1081 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001082
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301083 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1084 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301085 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301086 platform_get_snd_device_name(usecase->out_snd_device),
1087 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301088 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1089 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1090 usecase, uc_info, snd_device);
1091 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1092 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1093 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1094 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1095 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1096 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1097 ((force_restart_session) ||
1098 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301099 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1100 __func__, use_case_table[usecase->id],
1101 platform_get_snd_device_name(usecase->out_snd_device));
1102 disable_audio_route(adev, usecase);
1103 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301104 /* Enable existing usecase on derived playback device */
1105 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301106 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301107 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108 }
1109 }
1110
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301111 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1112 num_uc_to_switch);
1113
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001115 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301117 /* Make sure the previous devices to be disabled first and then enable the
1118 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001119 list_for_each(node, &adev->usecase_list) {
1120 usecase = node_to_item(node, struct audio_usecase, list);
1121 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001122 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 }
1124 }
1125
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001126 list_for_each(node, &adev->usecase_list) {
1127 usecase = node_to_item(node, struct audio_usecase, list);
1128 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301129 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001130 }
1131 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 /* Re-route all the usecases on the shared backend other than the
1134 specified usecase to new snd devices */
1135 list_for_each(node, &adev->usecase_list) {
1136 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301137 /* Update the out_snd_device only before enabling the audio route */
1138 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301139 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301140 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301141 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301142 use_case_table[usecase->id],
1143 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001144 /* Update voc calibration before enabling VoIP route */
1145 if (usecase->type == VOIP_CALL)
1146 status = platform_switch_voice_call_device_post(adev->platform,
1147 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001148 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301149 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301150 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001151 }
1152 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153 }
1154}
1155
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301156static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001157 struct audio_usecase *uc_info,
1158 snd_device_t snd_device)
1159{
1160 struct listnode *node;
1161 struct audio_usecase *usecase;
1162 bool switch_device[AUDIO_USECASE_MAX];
1163 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301164 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001165 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001166
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301167 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1168 snd_device);
1169 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301170
1171 /*
1172 * Make sure out devices is checked against out codec backend device and
1173 * also in devices against in codec backend. Checking out device against in
1174 * codec backend or vice versa causes issues.
1175 */
1176 if (uc_info->type == PCM_CAPTURE)
1177 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001178 /*
1179 * This function is to make sure that all the active capture usecases
1180 * are always routed to the same input sound device.
1181 * For example, if audio-record and voice-call usecases are currently
1182 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1183 * is received for voice call then we have to make sure that audio-record
1184 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1185 * because of the limitation that two devices cannot be enabled
1186 * at the same time if they share the same backend.
1187 */
1188 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1189 switch_device[i] = false;
1190
1191 list_for_each(node, &adev->usecase_list) {
1192 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301193 /*
1194 * TODO: Enhance below condition to handle BT sco/USB multi recording
1195 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001196 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001197 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301198 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301199 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301200 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301201 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001202 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001203 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1204 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001205 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001206 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001207 switch_device[usecase->id] = true;
1208 num_uc_to_switch++;
1209 }
1210 }
1211
1212 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001213 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301215 /* Make sure the previous devices to be disabled first and then enable the
1216 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001217 list_for_each(node, &adev->usecase_list) {
1218 usecase = node_to_item(node, struct audio_usecase, list);
1219 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001220 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001221 }
1222 }
1223
1224 list_for_each(node, &adev->usecase_list) {
1225 usecase = node_to_item(node, struct audio_usecase, list);
1226 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001227 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001228 }
1229 }
1230
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001231 /* Re-route all the usecases on the shared backend other than the
1232 specified usecase to new snd devices */
1233 list_for_each(node, &adev->usecase_list) {
1234 usecase = node_to_item(node, struct audio_usecase, list);
1235 /* Update the in_snd_device only before enabling the audio route */
1236 if (switch_device[usecase->id] ) {
1237 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001238 if (usecase->type != VOICE_CALL) {
1239 /* Update voc calibration before enabling VoIP route */
1240 if (usecase->type == VOIP_CALL)
1241 status = platform_switch_voice_call_device_post(adev->platform,
1242 usecase->out_snd_device,
1243 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301244 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001245 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001246 }
1247 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001248 }
1249}
1250
Mingming Yin3a941d42016-02-17 18:08:05 -08001251static void reset_hdmi_sink_caps(struct stream_out *out) {
1252 int i = 0;
1253
1254 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1255 out->supported_channel_masks[i] = 0;
1256 }
1257 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1258 out->supported_formats[i] = 0;
1259 }
1260 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1261 out->supported_sample_rates[i] = 0;
1262 }
1263}
1264
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001265/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001266static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267{
Mingming Yin3a941d42016-02-17 18:08:05 -08001268 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001269 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270
Mingming Yin3a941d42016-02-17 18:08:05 -08001271 reset_hdmi_sink_caps(out);
1272
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001273 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001274 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001275 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001276 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001277 }
1278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001281 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001282 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001283 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1284 case 6:
1285 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1286 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1287 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1288 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1290 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001291 break;
1292 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001293 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001294 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 break;
1296 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001297
1298 // check channel format caps
1299 i = 0;
1300 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1301 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1302 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1303 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1304 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1305 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1306 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1307 }
1308
1309 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1310 ALOGV(":%s HDMI supports DTS format", __func__);
1311 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1312 }
1313
1314 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1315 ALOGV(":%s HDMI supports DTS HD format", __func__);
1316 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1317 }
1318
1319
1320 // check sample rate caps
1321 i = 0;
1322 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1323 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1324 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1325 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1326 }
1327 }
1328
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001329 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330}
1331
Alexy Josephb1379942016-01-29 15:49:38 -08001332audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001333 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001334{
1335 struct audio_usecase *usecase;
1336 struct listnode *node;
1337
1338 list_for_each(node, &adev->usecase_list) {
1339 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001340 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001341 ALOGV("%s: usecase id %d", __func__, usecase->id);
1342 return usecase->id;
1343 }
1344 }
1345 return USECASE_INVALID;
1346}
1347
Alexy Josephb1379942016-01-29 15:49:38 -08001348struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001349 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350{
1351 struct audio_usecase *usecase;
1352 struct listnode *node;
1353
1354 list_for_each(node, &adev->usecase_list) {
1355 usecase = node_to_item(node, struct audio_usecase, list);
1356 if (usecase->id == uc_id)
1357 return usecase;
1358 }
1359 return NULL;
1360}
1361
Dhananjay Kumard4833242016-10-06 22:09:12 +05301362struct stream_in *get_next_active_input(const struct audio_device *adev)
1363{
1364 struct audio_usecase *usecase;
1365 struct listnode *node;
1366
1367 list_for_each_reverse(node, &adev->usecase_list) {
1368 usecase = node_to_item(node, struct audio_usecase, list);
1369 if (usecase->type == PCM_CAPTURE)
1370 return usecase->stream.in;
1371 }
1372 return NULL;
1373}
1374
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301375/*
1376 * is a true native playback active
1377 */
1378bool audio_is_true_native_stream_active(struct audio_device *adev)
1379{
1380 bool active = false;
1381 int i = 0;
1382 struct listnode *node;
1383
1384 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1385 ALOGV("%s:napb: not in true mode or non hdphones device",
1386 __func__);
1387 active = false;
1388 goto exit;
1389 }
1390
1391 list_for_each(node, &adev->usecase_list) {
1392 struct audio_usecase *uc;
1393 uc = node_to_item(node, struct audio_usecase, list);
1394 struct stream_out *curr_out =
1395 (struct stream_out*) uc->stream.out;
1396
1397 if (curr_out && PCM_PLAYBACK == uc->type) {
1398 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1399 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1400 uc->id, curr_out->sample_rate,
1401 curr_out->bit_width,
1402 platform_get_snd_device_name(uc->out_snd_device));
1403
1404 if (is_offload_usecase(uc->id) &&
1405 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1406 active = true;
1407 ALOGD("%s:napb:native stream detected", __func__);
1408 }
1409 }
1410 }
1411exit:
1412 return active;
1413}
1414
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301415/*
1416 * if native DSD playback active
1417 */
1418bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1419{
1420 bool active = false;
1421 struct listnode *node = NULL;
1422 struct audio_usecase *uc = NULL;
1423 struct stream_out *curr_out = NULL;
1424
1425 list_for_each(node, &adev->usecase_list) {
1426 uc = node_to_item(node, struct audio_usecase, list);
1427 curr_out = (struct stream_out*) uc->stream.out;
1428
1429 if (curr_out && PCM_PLAYBACK == uc->type &&
1430 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1431 active = true;
1432 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301433 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301434 }
1435 }
1436 return active;
1437}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301438
1439static bool force_device_switch(struct audio_usecase *usecase)
1440{
1441 bool ret = false;
1442 bool is_it_true_mode = false;
1443
1444 if (is_offload_usecase(usecase->id) &&
1445 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001446 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1447 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1448 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301449 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1450 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1451 (!is_it_true_mode && adev->native_playback_enabled)){
1452 ret = true;
1453 ALOGD("napb: time to toggle native mode");
1454 }
1455 }
1456
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301457 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301458 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1459 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301460 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001461 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301462 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301463 ALOGD("Force a2dp device switch to update new encoder config");
1464 ret = true;
1465 }
1466
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301467 return ret;
1468}
1469
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001470int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001472 snd_device_t out_snd_device = SND_DEVICE_NONE;
1473 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474 struct audio_usecase *usecase = NULL;
1475 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001476 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001477 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001478 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001479 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301481 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1482
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 usecase = get_usecase_from_list(adev, uc_id);
1484 if (usecase == NULL) {
1485 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1486 return -EINVAL;
1487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001489 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001490 (usecase->type == VOIP_CALL) ||
1491 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301492 if(usecase->stream.out == NULL) {
1493 ALOGE("%s: stream.out is NULL", __func__);
1494 return -EINVAL;
1495 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001496 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001497 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001498 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 usecase->devices = usecase->stream.out->devices;
1500 } else {
1501 /*
1502 * If the voice call is active, use the sound devices of voice call usecase
1503 * so that it would not result any device switch. All the usecases will
1504 * be switched to new device when select_devices() is called for voice call
1505 * usecase. This is to avoid switching devices for voice call when
1506 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001507 * choose voice call device only if the use case device is
1508 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001509 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001510 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001511 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001512 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001513 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1514 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301515 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1516 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001517 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 in_snd_device = vc_usecase->in_snd_device;
1519 out_snd_device = vc_usecase->out_snd_device;
1520 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001521 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001522 bool out_snd_device_backend_match = true;
1523 if (usecase->stream.out != NULL) {
1524 out_snd_device_backend_match = platform_check_backends_match(
1525 voip_usecase->out_snd_device,
1526 platform_get_output_snd_device(
1527 adev->platform,
1528 usecase->stream.out));
1529 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001530 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001531 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001532 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1533 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001534 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001535 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001536 in_snd_device = voip_usecase->in_snd_device;
1537 out_snd_device = voip_usecase->out_snd_device;
1538 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001539 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001540 hfp_ucid = audio_extn_hfp_get_usecase();
1541 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001542 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001543 in_snd_device = hfp_usecase->in_snd_device;
1544 out_snd_device = hfp_usecase->out_snd_device;
1545 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546 }
1547 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301548 if (usecase->stream.out == NULL) {
1549 ALOGE("%s: stream.out is NULL", __func__);
1550 return -EINVAL;
1551 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001552 usecase->devices = usecase->stream.out->devices;
1553 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001554 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001555 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001556 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001557 if (usecase->stream.out == adev->primary_output &&
1558 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001559 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001560 select_devices(adev, adev->active_input->usecase);
1561 }
1562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301564 if (usecase->stream.in == NULL) {
1565 ALOGE("%s: stream.in is NULL", __func__);
1566 return -EINVAL;
1567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 usecase->devices = usecase->stream.in->device;
1569 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001570 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001571 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001572 if (adev->active_input &&
1573 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301574 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1575 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1576 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001577 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001578 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001579 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1580 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001581 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001582 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001583 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584 }
1585 }
1586
1587 if (out_snd_device == usecase->out_snd_device &&
1588 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301589
1590 if (!force_device_switch(usecase))
1591 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 }
1593
sangwoobc677242013-08-08 16:53:43 +09001594 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001595 out_snd_device, platform_get_snd_device_name(out_snd_device),
1596 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 /*
1599 * Limitation: While in call, to do a device switch we need to disable
1600 * and enable both RX and TX devices though one of them is same as current
1601 * device.
1602 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001603 if ((usecase->type == VOICE_CALL) &&
1604 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1605 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001606 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001607 }
1608
1609 if (((usecase->type == VOICE_CALL) ||
1610 (usecase->type == VOIP_CALL)) &&
1611 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1612 /* Disable sidetone only if voice/voip call already exists */
1613 if (voice_is_call_state_active(adev) ||
1614 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001615 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001616
1617 /* Disable aanc only if voice call exists */
1618 if (voice_is_call_state_active(adev))
1619 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001620 }
1621
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 /* Disable current sound devices */
1623 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001624 disable_audio_route(adev, usecase);
1625 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 }
1627
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001628 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001629 disable_audio_route(adev, usecase);
1630 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631 }
1632
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001633 /* Applicable only on the targets that has external modem.
1634 * New device information should be sent to modem before enabling
1635 * the devices to reduce in-call device switch time.
1636 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001637 if ((usecase->type == VOICE_CALL) &&
1638 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1639 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001640 status = platform_switch_voice_call_enable_device_config(adev->platform,
1641 out_snd_device,
1642 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001643 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001644
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001645 /* Enable new sound devices */
1646 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001647 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301648 if (platform_check_codec_asrc_support(adev->platform))
1649 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001650 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 }
1652
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001653 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301654 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001655 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001656 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001657
Avinash Vaish71a8b972014-07-24 15:36:33 +05301658 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001659 status = platform_switch_voice_call_device_post(adev->platform,
1660 out_snd_device,
1661 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301662 enable_audio_route_for_voice_usecases(adev, usecase);
1663 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001664
sangwoo170731f2013-06-08 15:36:36 +09001665 usecase->in_snd_device = in_snd_device;
1666 usecase->out_snd_device = out_snd_device;
1667
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301668 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1669 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301670 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001671 if ((24 == usecase->stream.out->bit_width) &&
1672 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1673 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1674 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1675 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1676 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1677 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1678 /*
1679 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1680 * configured device sample rate, if not update the COPP rate to be equal to the
1681 * device sample rate, else open COPP at stream sample rate
1682 */
1683 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1684 usecase->stream.out->sample_rate,
1685 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301686 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1687 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001688 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1689 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1690 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1691 }
1692
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001693 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001694 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001695 audio_extn_gef_notify_device_config(
1696 usecase->stream.out->devices,
1697 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001698 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001699 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001700 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301701 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001702 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001703
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001704 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001705 /* Enable aanc only if voice call exists */
1706 if (voice_is_call_state_active(adev))
1707 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1708
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001709 /* Enable sidetone only if other voice/voip call already exists */
1710 if (voice_is_call_state_active(adev) ||
1711 voice_extn_compress_voip_is_started(adev))
1712 voice_set_sidetone(adev, out_snd_device, true);
1713 }
1714
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001715 /* Applicable only on the targets that has external modem.
1716 * Enable device command should be sent to modem only after
1717 * enabling voice call mixer controls
1718 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001719 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001720 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1721 out_snd_device,
1722 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301723 ALOGD("%s: done",__func__);
1724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725 return status;
1726}
1727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728static int stop_input_stream(struct stream_in *in)
1729{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301730 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 struct audio_usecase *uc_info;
1732 struct audio_device *adev = in->dev;
1733
Eric Laurent994a6932013-07-17 11:51:42 -07001734 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001735 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 uc_info = get_usecase_from_list(adev, in->usecase);
1737 if (uc_info == NULL) {
1738 ALOGE("%s: Could not find the usecase (%d) in the list",
1739 __func__, in->usecase);
1740 return -EINVAL;
1741 }
1742
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001743 /* Close in-call recording streams */
1744 voice_check_and_stop_incall_rec_usecase(adev, in);
1745
Eric Laurent150dbfe2013-02-27 14:31:02 -08001746 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001747 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748
1749 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001750 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001752 list_remove(&uc_info->list);
1753 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001755 adev->active_input = get_next_active_input(adev);
1756
Eric Laurent994a6932013-07-17 11:51:42 -07001757 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 return ret;
1759}
1760
1761int start_input_stream(struct stream_in *in)
1762{
1763 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001764 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 struct audio_usecase *uc_info;
1766 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301767 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768
Mingming Yin2664a5b2015-09-03 10:53:11 -07001769 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1770 if (get_usecase_from_list(adev, usecase) == NULL)
1771 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301772 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1773 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001774
Naresh Tanniru80659832014-06-04 18:17:56 +05301775
1776 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301777 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301778 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301779 goto error_config;
1780 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301781
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001782 /* Check if source matches incall recording usecase criteria */
1783 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1784 if (ret)
1785 goto error_config;
1786 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001787 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1788
1789 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1790 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1791 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001792 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001793 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001794
Eric Laurentb23d5282013-05-14 15:27:20 -07001795 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 if (in->pcm_device_id < 0) {
1797 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1798 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001799 ret = -EINVAL;
1800 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001801 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802
1803 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001805
1806 if (!uc_info) {
1807 ret = -ENOMEM;
1808 goto error_config;
1809 }
1810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 uc_info->id = in->usecase;
1812 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001813 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001814 uc_info->devices = in->device;
1815 uc_info->in_snd_device = SND_DEVICE_NONE;
1816 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001818 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301819 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1820 adev->perf_lock_opts,
1821 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301824 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1825 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001826
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301827 if (audio_extn_cin_attached_usecase(in->usecase)) {
1828 ret = audio_extn_cin_start_input_stream(in);
1829 if (ret)
1830 goto error_open;
1831 else
1832 goto done_open;
1833 }
1834
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001835 unsigned int flags = PCM_IN;
1836 unsigned int pcm_open_retry_count = 0;
1837
1838 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1839 flags |= PCM_MMAP | PCM_NOIRQ;
1840 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001841 } else if (in->realtime) {
1842 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001843 }
1844
1845 while (1) {
1846 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1847 flags, &in->config);
1848 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1849 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1850 if (in->pcm != NULL) {
1851 pcm_close(in->pcm);
1852 in->pcm = NULL;
1853 }
1854 if (pcm_open_retry_count-- == 0) {
1855 ret = -EIO;
1856 goto error_open;
1857 }
1858 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1859 continue;
1860 }
1861 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001863
1864 ALOGV("%s: pcm_prepare", __func__);
1865 ret = pcm_prepare(in->pcm);
1866 if (ret < 0) {
1867 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1868 pcm_close(in->pcm);
1869 in->pcm = NULL;
1870 goto error_open;
1871 }
1872
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001873 register_in_stream(in);
1874 if (in->realtime) {
1875 ret = pcm_start(in->pcm);
1876 if (ret < 0)
1877 goto error_open;
1878 }
1879
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301880done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301881 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001882 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001883
Eric Laurentc8400632013-02-14 19:04:54 -08001884 return ret;
1885
1886error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301887 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001889error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301890 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301891 /*
1892 * sleep 50ms to allow sufficient time for kernel
1893 * drivers to recover incases like SSR.
1894 */
1895 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001896 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001897
1898 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899}
1900
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001901void lock_input_stream(struct stream_in *in)
1902{
1903 pthread_mutex_lock(&in->pre_lock);
1904 pthread_mutex_lock(&in->lock);
1905 pthread_mutex_unlock(&in->pre_lock);
1906}
1907
1908void lock_output_stream(struct stream_out *out)
1909{
1910 pthread_mutex_lock(&out->pre_lock);
1911 pthread_mutex_lock(&out->lock);
1912 pthread_mutex_unlock(&out->pre_lock);
1913}
1914
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001915/* must be called with out->lock locked */
1916static int send_offload_cmd_l(struct stream_out* out, int command)
1917{
1918 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1919
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001920 if (!cmd) {
1921 ALOGE("failed to allocate mem for command 0x%x", command);
1922 return -ENOMEM;
1923 }
1924
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001925 ALOGVV("%s %d", __func__, command);
1926
1927 cmd->cmd = command;
1928 list_add_tail(&out->offload_cmd_list, &cmd->node);
1929 pthread_cond_signal(&out->offload_cond);
1930 return 0;
1931}
1932
1933/* must be called iwth out->lock locked */
1934static void stop_compressed_output_l(struct stream_out *out)
1935{
1936 out->offload_state = OFFLOAD_STATE_IDLE;
1937 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001938 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 if (out->compr != NULL) {
1940 compress_stop(out->compr);
1941 while (out->offload_thread_blocked) {
1942 pthread_cond_wait(&out->cond, &out->lock);
1943 }
1944 }
1945}
1946
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001947bool is_offload_usecase(audio_usecase_t uc_id)
1948{
1949 unsigned int i;
1950 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1951 if (uc_id == offload_usecases[i])
1952 return true;
1953 }
1954 return false;
1955}
1956
Dhananjay Kumarac341582017-02-23 23:42:25 +05301957static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001958{
vivek mehta446c3962015-09-14 10:57:35 -07001959 audio_usecase_t ret_uc = USECASE_INVALID;
1960 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001961 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001962 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301963 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001964 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1965 else
1966 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001967
vivek mehta446c3962015-09-14 10:57:35 -07001968 pthread_mutex_lock(&adev->lock);
1969 if (get_usecase_from_list(adev, ret_uc) != NULL)
1970 ret_uc = USECASE_INVALID;
1971 pthread_mutex_unlock(&adev->lock);
1972
1973 return ret_uc;
1974 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001975
1976 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001977 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1978 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1979 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1980 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001981 break;
1982 }
1983 }
vivek mehta446c3962015-09-14 10:57:35 -07001984
1985 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1986 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001987}
1988
1989static void free_offload_usecase(struct audio_device *adev,
1990 audio_usecase_t uc_id)
1991{
vivek mehta446c3962015-09-14 10:57:35 -07001992 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001993 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001994
1995 if (!adev->multi_offload_enable)
1996 return;
1997
1998 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1999 if (offload_usecases[offload_uc_index] == uc_id) {
2000 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002001 break;
2002 }
2003 }
2004 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2005}
2006
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007static void *offload_thread_loop(void *context)
2008{
2009 struct stream_out *out = (struct stream_out *) context;
2010 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002011 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002012
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002013 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2014 set_sched_policy(0, SP_FOREGROUND);
2015 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2016
2017 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002018 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 for (;;) {
2020 struct offload_cmd *cmd = NULL;
2021 stream_callback_event_t event;
2022 bool send_callback = false;
2023
2024 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2025 __func__, list_empty(&out->offload_cmd_list),
2026 out->offload_state);
2027 if (list_empty(&out->offload_cmd_list)) {
2028 ALOGV("%s SLEEPING", __func__);
2029 pthread_cond_wait(&out->offload_cond, &out->lock);
2030 ALOGV("%s RUNNING", __func__);
2031 continue;
2032 }
2033
2034 item = list_head(&out->offload_cmd_list);
2035 cmd = node_to_item(item, struct offload_cmd, node);
2036 list_remove(item);
2037
2038 ALOGVV("%s STATE %d CMD %d out->compr %p",
2039 __func__, out->offload_state, cmd->cmd, out->compr);
2040
2041 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2042 free(cmd);
2043 break;
2044 }
2045
2046 if (out->compr == NULL) {
2047 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002048 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002049 pthread_cond_signal(&out->cond);
2050 continue;
2051 }
2052 out->offload_thread_blocked = true;
2053 pthread_mutex_unlock(&out->lock);
2054 send_callback = false;
2055 switch(cmd->cmd) {
2056 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002057 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002059 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060 send_callback = true;
2061 event = STREAM_CBK_EVENT_WRITE_READY;
2062 break;
2063 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002064 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302065 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002066 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302067 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002068 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302069 if (ret < 0)
2070 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302071 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302072 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002073 compress_drain(out->compr);
2074 else
2075 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302076 if (ret != -ENETRESET) {
2077 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302078 pthread_mutex_lock(&out->lock);
2079 out->send_new_metadata = 1;
2080 out->send_next_track_params = true;
2081 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302082 event = STREAM_CBK_EVENT_DRAIN_READY;
2083 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2084 } else
2085 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002086 break;
2087 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002088 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002090 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002091 send_callback = true;
2092 event = STREAM_CBK_EVENT_DRAIN_READY;
2093 break;
2094 default:
2095 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2096 break;
2097 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002098 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 out->offload_thread_blocked = false;
2100 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002101 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002102 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002104 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002105 free(cmd);
2106 }
2107
2108 pthread_cond_signal(&out->cond);
2109 while (!list_empty(&out->offload_cmd_list)) {
2110 item = list_head(&out->offload_cmd_list);
2111 list_remove(item);
2112 free(node_to_item(item, struct offload_cmd, node));
2113 }
2114 pthread_mutex_unlock(&out->lock);
2115
2116 return NULL;
2117}
2118
2119static int create_offload_callback_thread(struct stream_out *out)
2120{
2121 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2122 list_init(&out->offload_cmd_list);
2123 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2124 offload_thread_loop, out);
2125 return 0;
2126}
2127
2128static int destroy_offload_callback_thread(struct stream_out *out)
2129{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002130 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131 stop_compressed_output_l(out);
2132 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2133
2134 pthread_mutex_unlock(&out->lock);
2135 pthread_join(out->offload_thread, (void **) NULL);
2136 pthread_cond_destroy(&out->offload_cond);
2137
2138 return 0;
2139}
2140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141static int stop_output_stream(struct stream_out *out)
2142{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302143 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 struct audio_usecase *uc_info;
2145 struct audio_device *adev = out->dev;
2146
Eric Laurent994a6932013-07-17 11:51:42 -07002147 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002148 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 uc_info = get_usecase_from_list(adev, out->usecase);
2150 if (uc_info == NULL) {
2151 ALOGE("%s: Could not find the usecase (%d) in the list",
2152 __func__, out->usecase);
2153 return -EINVAL;
2154 }
2155
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002156 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302157 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002158 if (adev->visualizer_stop_output != NULL)
2159 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002160
2161 audio_extn_dts_remove_state_notifier_node(out->usecase);
2162
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002163 if (adev->offload_effects_stop_output != NULL)
2164 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2165 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002166
Eric Laurent150dbfe2013-02-27 14:31:02 -08002167 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002168 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002169
2170 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002171 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002173 list_remove(&uc_info->list);
2174 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002176 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302177 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002178 ALOGV("Disable passthrough , reset mixer to pcm");
2179 /* NO_PASSTHROUGH */
2180 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002181 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002182 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2183 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002184
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302185 /* Must be called after removing the usecase from list */
2186 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302187 audio_extn_keep_alive_start();
2188
Eric Laurent994a6932013-07-17 11:51:42 -07002189 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 return ret;
2191}
2192
2193int start_output_stream(struct stream_out *out)
2194{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 struct audio_usecase *uc_info;
2197 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302198 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002199 char mixer_ctl_name[128];
2200 struct mixer_ctl *ctl = NULL;
2201 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002203 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2204 ret = -EINVAL;
2205 goto error_config;
2206 }
2207
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302208 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2209 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2210 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302211
Naresh Tanniru80659832014-06-04 18:17:56 +05302212 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302213 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302214 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302215 goto error_config;
2216 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302217
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302218 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2219 if (!audio_extn_a2dp_is_ready()) {
2220 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2221 //combo usecase just by pass a2dp
2222 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2223 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2224 } else {
2225 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2226 ret = -EAGAIN;
2227 goto error_config;
2228 }
2229 }
2230 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002231 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 if (out->pcm_device_id < 0) {
2233 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2234 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002235 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002236 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 }
2238
2239 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002240
2241 if (!uc_info) {
2242 ret = -ENOMEM;
2243 goto error_config;
2244 }
2245
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 uc_info->id = out->usecase;
2247 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002248 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002249 uc_info->devices = out->devices;
2250 uc_info->in_snd_device = SND_DEVICE_NONE;
2251 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002252 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302254 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2255 adev->perf_lock_opts,
2256 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302257
2258 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2259 audio_extn_keep_alive_stop();
2260 if (audio_extn_passthru_is_enabled() &&
2261 audio_extn_passthru_is_passthrough_stream(out)) {
2262 audio_extn_passthru_on_start(out);
2263 audio_extn_passthru_update_stream_configuration(adev, out);
2264 }
2265 }
2266
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002267 select_devices(adev, out->usecase);
2268
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002269 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2270 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002271 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002272 unsigned int flags = PCM_OUT;
2273 unsigned int pcm_open_retry_count = 0;
2274 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2275 flags |= PCM_MMAP | PCM_NOIRQ;
2276 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002277 } else if (out->realtime) {
2278 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002279 } else
2280 flags |= PCM_MONOTONIC;
2281
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002282 if ((adev->vr_audio_mode_enabled) &&
2283 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2284 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2285 "PCM_Dev %d Topology", out->pcm_device_id);
2286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2287 if (!ctl) {
2288 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2289 __func__, mixer_ctl_name);
2290 } else {
2291 //if success use ULLPP
2292 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2293 __func__, mixer_ctl_name, out->pcm_device_id);
2294 //There is a still a possibility that some sessions
2295 // that request for FAST|RAW when 3D audio is active
2296 //can go through ULLPP. Ideally we expects apps to
2297 //listen to audio focus and stop concurrent playback
2298 //Also, we will look for mode flag (voice_in_communication)
2299 //before enabling the realtime flag.
2300 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2301 }
2302 }
2303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002304 while (1) {
2305 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2306 flags, &out->config);
2307 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2308 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2309 if (out->pcm != NULL) {
2310 pcm_close(out->pcm);
2311 out->pcm = NULL;
2312 }
2313 if (pcm_open_retry_count-- == 0) {
2314 ret = -EIO;
2315 goto error_open;
2316 }
2317 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2318 continue;
2319 }
2320 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002321 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002322
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002323 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2324 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002325
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002326 ALOGV("%s: pcm_prepare", __func__);
2327 if (pcm_is_ready(out->pcm)) {
2328 ret = pcm_prepare(out->pcm);
2329 if (ret < 0) {
2330 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2331 pcm_close(out->pcm);
2332 out->pcm = NULL;
2333 goto error_open;
2334 }
2335 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302336 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2337 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002339 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2340 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002342 out->compr = compress_open(adev->snd_card,
2343 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 COMPRESS_IN, &out->compr_config);
2345 if (out->compr && !is_compress_ready(out->compr)) {
2346 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2347 compress_close(out->compr);
2348 out->compr = NULL;
2349 ret = -EIO;
2350 goto error_open;
2351 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302352 /* compress_open sends params of the track, so reset the flag here */
2353 out->is_compr_metadata_avail = false;
2354
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 if (out->offload_callback)
2356 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002357
Fred Oh3f43e742015-03-04 18:42:34 -08002358 /* Since small bufs uses blocking writes, a write will be blocked
2359 for the default max poll time (20s) in the event of an SSR.
2360 Reduce the poll time to observe and deal with SSR faster.
2361 */
Ashish Jain5106d362016-05-11 19:23:33 +05302362 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002363 compress_set_max_poll_wait(out->compr, 1000);
2364 }
2365
Manish Dewangan69426c82017-01-30 17:35:36 +05302366 audio_extn_utils_compress_set_render_mode(out);
2367
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002368 audio_extn_dts_create_state_notifier_node(out->usecase);
2369 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2370 popcount(out->channel_mask),
2371 out->playback_started);
2372
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002373#ifdef DS1_DOLBY_DDP_ENABLED
2374 if (audio_extn_is_dolby_format(out->format))
2375 audio_extn_dolby_send_ddp_endp_params(adev);
2376#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302377 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2378 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002379 if (adev->visualizer_start_output != NULL)
2380 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2381 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302382 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002383 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002384 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002386
2387 if (ret == 0) {
2388 register_out_stream(out);
2389 if (out->realtime) {
2390 ret = pcm_start(out->pcm);
2391 if (ret < 0)
2392 goto error_open;
2393 }
2394 }
2395
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302396 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002397 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002398
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002399 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002400error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302401 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002403error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302404 /*
2405 * sleep 50ms to allow sufficient time for kernel
2406 * drivers to recover incases like SSR.
2407 */
2408 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002409 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410}
2411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412static int check_input_parameters(uint32_t sample_rate,
2413 audio_format_t format,
2414 int channel_count)
2415{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002416 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302418 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2419 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2420 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002421 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302422 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002423
2424 switch (channel_count) {
2425 case 1:
2426 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302427 case 3:
2428 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002429 case 6:
2430 break;
2431 default:
2432 ret = -EINVAL;
2433 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434
2435 switch (sample_rate) {
2436 case 8000:
2437 case 11025:
2438 case 12000:
2439 case 16000:
2440 case 22050:
2441 case 24000:
2442 case 32000:
2443 case 44100:
2444 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302445 case 96000:
2446 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447 break;
2448 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002449 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 }
2451
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002452 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453}
2454
2455static size_t get_input_buffer_size(uint32_t sample_rate,
2456 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002457 int channel_count,
2458 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459{
2460 size_t size = 0;
2461
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002462 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2463 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002465 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002466 if (is_low_latency)
2467 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302468
2469 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002471 /* make sure the size is multiple of 32 bytes
2472 * At 48 kHz mono 16-bit PCM:
2473 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2474 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2475 */
2476 size += 0x1f;
2477 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002478
2479 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480}
2481
Ashish Jain058165c2016-09-28 23:18:48 +05302482static size_t get_output_period_size(uint32_t sample_rate,
2483 audio_format_t format,
2484 int channel_count,
2485 int duration /*in millisecs*/)
2486{
2487 size_t size = 0;
2488 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2489
2490 if ((duration == 0) || (sample_rate == 0) ||
2491 (bytes_per_sample == 0) || (channel_count == 0)) {
2492 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2493 bytes_per_sample, channel_count);
2494 return -EINVAL;
2495 }
2496
2497 size = (sample_rate *
2498 duration *
2499 bytes_per_sample *
2500 channel_count) / 1000;
2501 /*
2502 * To have same PCM samples for all channels, the buffer size requires to
2503 * be multiple of (number of channels * bytes per sample)
2504 * For writes to succeed, the buffer must be written at address which is multiple of 32
2505 */
2506 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2507
2508 return (size/(channel_count * bytes_per_sample));
2509}
2510
Ashish Jain5106d362016-05-11 19:23:33 +05302511static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2512{
2513 uint64_t actual_frames_rendered = 0;
2514 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2515
2516 /* This adjustment accounts for buffering after app processor.
2517 * It is based on estimated DSP latency per use case, rather than exact.
2518 */
2519 int64_t platform_latency = platform_render_latency(out->usecase) *
2520 out->sample_rate / 1000000LL;
2521
2522 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2523 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2524 * hence only estimate.
2525 */
2526 int64_t signed_frames = out->written - kernel_buffer_size;
2527
2528 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2529
2530 if (signed_frames > 0)
2531 actual_frames_rendered = signed_frames;
2532
2533 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2534 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2535 (long long int)out->written, (int)kernel_buffer_size,
2536 audio_bytes_per_sample(out->compr_config.codec->format),
2537 popcount(out->channel_mask));
2538
2539 return actual_frames_rendered;
2540}
2541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2543{
2544 struct stream_out *out = (struct stream_out *)stream;
2545
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547}
2548
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002549static int out_set_sample_rate(struct audio_stream *stream __unused,
2550 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551{
2552 return -ENOSYS;
2553}
2554
2555static size_t out_get_buffer_size(const struct audio_stream *stream)
2556{
2557 struct stream_out *out = (struct stream_out *)stream;
2558
Dhananjay Kumarac341582017-02-23 23:42:25 +05302559 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002560 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002561 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2562 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302563 else if (is_offload_usecase(out->usecase) &&
2564 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302565 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002566
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002567 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002568 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569}
2570
2571static uint32_t out_get_channels(const struct audio_stream *stream)
2572{
2573 struct stream_out *out = (struct stream_out *)stream;
2574
2575 return out->channel_mask;
2576}
2577
2578static audio_format_t out_get_format(const struct audio_stream *stream)
2579{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002580 struct stream_out *out = (struct stream_out *)stream;
2581
2582 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583}
2584
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002585static int out_set_format(struct audio_stream *stream __unused,
2586 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587{
2588 return -ENOSYS;
2589}
2590
2591static int out_standby(struct audio_stream *stream)
2592{
2593 struct stream_out *out = (struct stream_out *)stream;
2594 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302596 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2597 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002599 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002601 if (adev->adm_deregister_stream)
2602 adev->adm_deregister_stream(adev->adm_data, out->handle);
2603
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002604 if (is_offload_usecase(out->usecase))
2605 stop_compressed_output_l(out);
2606
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002607 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002609 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2610 voice_extn_compress_voip_close_output_stream(stream);
2611 pthread_mutex_unlock(&adev->lock);
2612 pthread_mutex_unlock(&out->lock);
2613 ALOGD("VOIP output entered standby");
2614 return 0;
2615 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002616 if (out->pcm) {
2617 pcm_close(out->pcm);
2618 out->pcm = NULL;
2619 }
2620 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002621 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302622 out->send_next_track_params = false;
2623 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002624 out->gapless_mdata.encoder_delay = 0;
2625 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002626 if (out->compr != NULL) {
2627 compress_close(out->compr);
2628 out->compr = NULL;
2629 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002630 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002632 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 }
2634 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302635 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636 return 0;
2637}
2638
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002639static int out_dump(const struct audio_stream *stream __unused,
2640 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641{
2642 return 0;
2643}
2644
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002645static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2646{
2647 int ret = 0;
2648 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002649
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002650 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002651 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002652 return -EINVAL;
2653 }
2654
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302655 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002656
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002657 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2658 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302659 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002660 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002661 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2662 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302663 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002664 }
2665
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002666 ALOGV("%s new encoder delay %u and padding %u", __func__,
2667 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2668
2669 return 0;
2670}
2671
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002672static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2673{
2674 return out == adev->primary_output || out == adev->voice_tx_output;
2675}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2678{
2679 struct stream_out *out = (struct stream_out *)stream;
2680 struct audio_device *adev = out->dev;
2681 struct str_parms *parms;
2682 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002683 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684
sangwoobc677242013-08-08 16:53:43 +09002685 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002686 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302688 if (!parms)
2689 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002690 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2691 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002693 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002694 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002696 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002697 * When HDMI cable is unplugged the music playback is paused and
2698 * the policy manager sends routing=0. But the audioflinger continues
2699 * to write data until standby time (3sec). As the HDMI core is
2700 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002701 * Avoid this by routing audio to speaker until standby.
2702 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002703 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2704 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302705 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002706 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2707 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002708 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302709 /*
2710 * When A2DP is disconnected the
2711 * music playback is paused and the policy manager sends routing=0
2712 * But the audioflingercontinues to write data until standby time
2713 * (3sec). As BT is turned off, the write gets blocked.
2714 * Avoid this by routing audio to speaker until standby.
2715 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002716 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302717 (val == AUDIO_DEVICE_NONE)) {
2718 val = AUDIO_DEVICE_OUT_SPEAKER;
2719 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302720 /* To avoid a2dp to sco overlapping / BT device improper state
2721 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302722 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302723 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2724 if (!audio_extn_a2dp_is_ready()) {
2725 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2726 //combo usecase just by pass a2dp
2727 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2728 val = AUDIO_DEVICE_OUT_SPEAKER;
2729 } else {
2730 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2731 /* update device to a2dp and don't route as BT returned error
2732 * However it is still possible a2dp routing called because
2733 * of current active device disconnection (like wired headset)
2734 */
2735 out->devices = val;
2736 pthread_mutex_unlock(&out->lock);
2737 pthread_mutex_unlock(&adev->lock);
2738 goto error;
2739 }
2740 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302741 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002742 /*
2743 * select_devices() call below switches all the usecases on the same
2744 * backend to the new device. Refer to check_usecases_codec_backend() in
2745 * the select_devices(). But how do we undo this?
2746 *
2747 * For example, music playback is active on headset (deep-buffer usecase)
2748 * and if we go to ringtones and select a ringtone, low-latency usecase
2749 * will be started on headset+speaker. As we can't enable headset+speaker
2750 * and headset devices at the same time, select_devices() switches the music
2751 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2752 * So when the ringtone playback is completed, how do we undo the same?
2753 *
2754 * We are relying on the out_set_parameters() call on deep-buffer output,
2755 * once the ringtone playback is ended.
2756 * NOTE: We should not check if the current devices are same as new devices.
2757 * Because select_devices() must be called to switch back the music
2758 * playback to headset.
2759 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002760 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002761 audio_devices_t new_dev = val;
2762 bool same_dev = out->devices == new_dev;
2763 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002764
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002765 if (output_drives_call(adev, out)) {
2766 if(!voice_is_in_call(adev)) {
2767 if (adev->mode == AUDIO_MODE_IN_CALL) {
2768 adev->current_call_output = out;
2769 ret = voice_start_call(adev);
2770 }
2771 } else {
2772 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002773 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002774 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002775 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002776
2777 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002778 if (!same_dev) {
2779 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302780 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2781 adev->perf_lock_opts,
2782 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002783 if (adev->adm_on_routing_change)
2784 adev->adm_on_routing_change(adev->adm_data,
2785 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002786 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002787 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302788 if (!same_dev)
2789 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002790 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002791 }
2792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002794 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002796
2797 if (out == adev->primary_output) {
2798 pthread_mutex_lock(&adev->lock);
2799 audio_extn_set_parameters(adev, parms);
2800 pthread_mutex_unlock(&adev->lock);
2801 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002802 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002803 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002804 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002805
2806 audio_extn_dts_create_state_notifier_node(out->usecase);
2807 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2808 popcount(out->channel_mask),
2809 out->playback_started);
2810
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002811 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002812 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002813
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302814 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2815 if (err >= 0) {
2816 strlcpy(out->profile, value, sizeof(out->profile));
2817 ALOGV("updating stream profile with value '%s'", out->profile);
2818 lock_output_stream(out);
2819 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2820 &adev->streams_output_cfg_list,
2821 out->devices, out->flags, out->format,
2822 out->sample_rate, out->bit_width,
2823 out->channel_mask, out->profile,
2824 &out->app_type_cfg);
2825 pthread_mutex_unlock(&out->lock);
2826 }
2827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302829error:
Eric Laurent994a6932013-07-17 11:51:42 -07002830 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 return ret;
2832}
2833
2834static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2835{
2836 struct stream_out *out = (struct stream_out *)stream;
2837 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002838 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 char value[256];
2840 struct str_parms *reply = str_parms_create();
2841 size_t i, j;
2842 int ret;
2843 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002844
2845 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002846 if (reply) {
2847 str_parms_destroy(reply);
2848 }
2849 if (query) {
2850 str_parms_destroy(query);
2851 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002852 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2853 return NULL;
2854 }
2855
Eric Laurent994a6932013-07-17 11:51:42 -07002856 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2858 if (ret >= 0) {
2859 value[0] = '\0';
2860 i = 0;
2861 while (out->supported_channel_masks[i] != 0) {
2862 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2863 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2864 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002865 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002867 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 first = false;
2869 break;
2870 }
2871 }
2872 i++;
2873 }
2874 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2875 str = str_parms_to_str(reply);
2876 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002877 voice_extn_out_get_parameters(out, query, reply);
2878 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002879 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002880 free(str);
2881 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002882 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002884
Alexy Joseph62142aa2015-11-16 15:10:34 -08002885
2886 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2887 if (ret >= 0) {
2888 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302889 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2890 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002891 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302892 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002893 } else {
2894 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302895 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002896 }
2897 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002898 if (str)
2899 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002900 str = str_parms_to_str(reply);
2901 }
2902
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002903 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2904 if (ret >= 0) {
2905 value[0] = '\0';
2906 i = 0;
2907 first = true;
2908 while (out->supported_formats[i] != 0) {
2909 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2910 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2911 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002912 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002913 }
2914 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2915 first = false;
2916 break;
2917 }
2918 }
2919 i++;
2920 }
2921 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002922 if (str)
2923 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002924 str = str_parms_to_str(reply);
2925 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002926
2927 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2928 if (ret >= 0) {
2929 value[0] = '\0';
2930 i = 0;
2931 first = true;
2932 while (out->supported_sample_rates[i] != 0) {
2933 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2934 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2935 if (!first) {
2936 strlcat(value, "|", sizeof(value));
2937 }
2938 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2939 first = false;
2940 break;
2941 }
2942 }
2943 i++;
2944 }
2945 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2946 if (str)
2947 free(str);
2948 str = str_parms_to_str(reply);
2949 }
2950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 str_parms_destroy(query);
2952 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002953 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954 return str;
2955}
2956
2957static uint32_t out_get_latency(const struct audio_stream_out *stream)
2958{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002959 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002960 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002961 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962
Alexy Josephaa54c872014-12-03 02:46:47 -08002963 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302964 lock_output_stream(out);
2965 latency = audio_extn_utils_compress_get_dsp_latency(out);
2966 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002967 } else if (out->realtime) {
2968 // since the buffer won't be filled up faster than realtime,
2969 // return a smaller number
2970 if (out->config.rate)
2971 period_ms = (out->af_period_multiplier * out->config.period_size *
2972 1000) / (out->config.rate);
2973 else
2974 period_ms = 0;
2975 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002976 } else {
2977 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002978 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002979 }
2980
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002981 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2982 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2983 latency += audio_extn_a2dp_get_encoder_latency();
2984
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302985 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002986 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987}
2988
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302989static float AmpToDb(float amplification)
2990{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302991 float db = DSD_VOLUME_MIN_DB;
2992 if (amplification > 0) {
2993 db = 20 * log10(amplification);
2994 if(db < DSD_VOLUME_MIN_DB)
2995 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302996 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302997 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302998}
2999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000static int out_set_volume(struct audio_stream_out *stream, float left,
3001 float right)
3002{
Eric Laurenta9024de2013-04-04 09:19:12 -07003003 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 int volume[2];
3005
Eric Laurenta9024de2013-04-04 09:19:12 -07003006 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3007 /* only take left channel into account: the API is for stereo anyway */
3008 out->muted = (left == 0.0f);
3009 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003010 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303011 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003012 /*
3013 * Set mute or umute on HDMI passthrough stream.
3014 * Only take left channel into account.
3015 * Mute is 0 and unmute 1
3016 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303017 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303018 } else if (out->format == AUDIO_FORMAT_DSD){
3019 char mixer_ctl_name[128] = "DSD Volume";
3020 struct audio_device *adev = out->dev;
3021 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3022
3023 if (!ctl) {
3024 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3025 __func__, mixer_ctl_name);
3026 return -EINVAL;
3027 }
3028 volume[0] = (int)(AmpToDb(left));
3029 volume[1] = (int)(AmpToDb(right));
3030 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3031 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003032 } else {
3033 char mixer_ctl_name[128];
3034 struct audio_device *adev = out->dev;
3035 struct mixer_ctl *ctl;
3036 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003037 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003038
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003039 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3040 "Compress Playback %d Volume", pcm_device_id);
3041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3042 if (!ctl) {
3043 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3044 __func__, mixer_ctl_name);
3045 return -EINVAL;
3046 }
3047 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3048 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3049 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3050 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003052 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 return -ENOSYS;
3055}
3056
3057static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3058 size_t bytes)
3059{
3060 struct stream_out *out = (struct stream_out *)stream;
3061 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303062 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003063 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003065 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303066
Naresh Tanniru80659832014-06-04 18:17:56 +05303067 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003068
Dhananjay Kumarac341582017-02-23 23:42:25 +05303069 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303070 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303071 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3072 pthread_mutex_unlock(&out->lock);
3073 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303074 } else {
3075 /* increase written size during SSR to avoid mismatch
3076 * with the written frames count in AF
3077 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003078 // bytes per frame
3079 size_t bpf = audio_bytes_per_sample(out->format) *
3080 audio_channel_count_from_out_mask(out->channel_mask);
3081 if (bpf != 0)
3082 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303083 ALOGD(" %s: sound card is not active/SSR state", __func__);
3084 ret= -EIO;
3085 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303086 }
3087 }
3088
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303089 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303090 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3091 if (audio_bytes_per_sample(out->format) != 0)
3092 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3093 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303094 goto exit;
3095 }
3096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003098 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003099 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003100 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3101 ret = voice_extn_compress_voip_start_output_stream(out);
3102 else
3103 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003104 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003107 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 goto exit;
3109 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003110
3111 if (last_known_cal_step != -1) {
3112 ALOGD("%s: retry previous failed cal level set", __func__);
3113 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3114 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
Ashish Jain81eb2a82015-05-13 10:52:34 +05303117 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003118 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303119 adev->is_channel_status_set = true;
3120 }
3121
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003122 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003123 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003124 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003125 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003126 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3127 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303128 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3129 ALOGD("copl(%p):send next track params in gapless", out);
3130 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3131 out->send_next_track_params = false;
3132 out->is_compr_metadata_avail = false;
3133 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003134 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303135 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303136 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003137
Ashish Jain83a6cc22016-06-28 14:34:17 +05303138 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303139 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303140 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303141 pthread_mutex_unlock(&out->lock);
3142 return -EINVAL;
3143 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303144 audio_format_t dst_format = out->hal_op_format;
3145 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303146
3147 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3148 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3149
Ashish Jain83a6cc22016-06-28 14:34:17 +05303150 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303151 dst_format,
3152 buffer,
3153 src_format,
3154 frames);
3155
Ashish Jain83a6cc22016-06-28 14:34:17 +05303156 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303157 bytes_to_write);
3158
3159 /*Convert written bytes in audio flinger format*/
3160 if (ret > 0)
3161 ret = ((ret * format_to_bitwidth_table[out->format]) /
3162 format_to_bitwidth_table[dst_format]);
3163 }
3164 } else
3165 ret = compress_write(out->compr, buffer, bytes);
3166
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303167 if (ret < 0)
3168 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303169 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303170 /*msg to cb thread only if non blocking write is enabled*/
3171 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303172 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003173 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303174 } else if (-ENETRESET == ret) {
3175 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3176 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3177 pthread_mutex_unlock(&out->lock);
3178 out_standby(&out->stream.common);
3179 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003180 }
Ashish Jain5106d362016-05-11 19:23:33 +05303181 if ( ret == (ssize_t)bytes && !out->non_blocking)
3182 out->written += bytes;
3183
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303184 /* Call compr start only when non-zero bytes of data is there to be rendered */
3185 if (!out->playback_started && ret > 0) {
3186 int status = compress_start(out->compr);
3187 if (status < 0) {
3188 ret = status;
3189 ALOGE("%s: compr start failed with err %d", __func__, errno);
3190 goto exit;
3191 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003192 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 out->playback_started = 1;
3194 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003195
3196 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3197 popcount(out->channel_mask),
3198 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 }
3200 pthread_mutex_unlock(&out->lock);
3201 return ret;
3202 } else {
3203 if (out->pcm) {
3204 if (out->muted)
3205 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003206
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303207 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003208
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003209 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003210
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003211 if (out->config.rate)
3212 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3213 out->config.rate;
3214
3215 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3216
3217 request_out_focus(out, ns);
3218
3219 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003220 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003221 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303222 out->convert_buffer != NULL) {
3223
3224 memcpy_by_audio_format(out->convert_buffer,
3225 out->hal_op_format,
3226 buffer,
3227 out->hal_ip_format,
3228 out->config.period_size * out->config.channels);
3229
3230 ret = pcm_write(out->pcm, out->convert_buffer,
3231 (out->config.period_size *
3232 out->config.channels *
3233 format_to_bitwidth_table[out->hal_op_format]));
3234 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003235 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303236 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003237
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003238 release_out_focus(out);
3239
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303240 if (ret < 0)
3241 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303242 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3243 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3244 else
3245 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 }
3248
3249exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303250 /* ToDo: There may be a corner case when SSR happens back to back during
3251 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303252 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303253 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303254 }
3255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 pthread_mutex_unlock(&out->lock);
3257
3258 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003259 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003260 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303261 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303262 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303263 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303264 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303265 out->standby = true;
3266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303268 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3269 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3270 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 }
3272 return bytes;
3273}
3274
3275static int out_get_render_position(const struct audio_stream_out *stream,
3276 uint32_t *dsp_frames)
3277{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003278 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303279 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003280
3281 if (dsp_frames == NULL)
3282 return -EINVAL;
3283
3284 *dsp_frames = 0;
3285 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003286 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303287
3288 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3289 * this operation and adev_close_output_stream(where out gets reset).
3290 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303291 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303292 *dsp_frames = get_actual_pcm_frames_rendered(out);
3293 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3294 return 0;
3295 }
3296
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003297 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303298 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303299 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003300 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303301 if (ret < 0)
3302 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003303 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303304 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003305 }
3306 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303307 if (-ENETRESET == ret) {
3308 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3309 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3310 return -EINVAL;
3311 } else if(ret < 0) {
3312 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3313 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303314 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3315 /*
3316 * Handle corner case where compress session is closed during SSR
3317 * and timestamp is queried
3318 */
3319 ALOGE(" ERROR: sound card not active, return error");
3320 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303321 } else {
3322 return 0;
3323 }
Zhou Song32a556e2015-05-05 10:46:56 +08003324 } else if (audio_is_linear_pcm(out->format)) {
3325 *dsp_frames = out->written;
3326 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 } else
3328 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329}
3330
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003331static int out_add_audio_effect(const struct audio_stream *stream __unused,
3332 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333{
3334 return 0;
3335}
3336
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003337static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3338 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339{
3340 return 0;
3341}
3342
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003343static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3344 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345{
3346 return -EINVAL;
3347}
3348
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003349static int out_get_presentation_position(const struct audio_stream_out *stream,
3350 uint64_t *frames, struct timespec *timestamp)
3351{
3352 struct stream_out *out = (struct stream_out *)stream;
3353 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003354 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003355
Ashish Jain5106d362016-05-11 19:23:33 +05303356 /* below piece of code is not guarded against any lock because audioFliner serializes
3357 * this operation and adev_close_output_stream( where out gets reset).
3358 */
3359 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303360 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303361 *frames = get_actual_pcm_frames_rendered(out);
3362 /* this is the best we can do */
3363 clock_gettime(CLOCK_MONOTONIC, timestamp);
3364 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3365 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3366 return 0;
3367 }
3368
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003369 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003370
Ashish Jain5106d362016-05-11 19:23:33 +05303371 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3372 ret = compress_get_tstamp(out->compr, &dsp_frames,
3373 &out->sample_rate);
3374 ALOGVV("%s rendered frames %ld sample_rate %d",
3375 __func__, dsp_frames, out->sample_rate);
3376 *frames = dsp_frames;
3377 if (ret < 0)
3378 ret = -errno;
3379 if (-ENETRESET == ret) {
3380 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3381 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3382 ret = -EINVAL;
3383 } else
3384 ret = 0;
3385 /* this is the best we can do */
3386 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003387 } else {
3388 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003389 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003390 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3391 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003392 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003393 // This adjustment accounts for buffering after app processor.
3394 // It is based on estimated DSP latency per use case, rather than exact.
3395 signed_frames -=
3396 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3397
Eric Laurent949a0892013-09-20 09:20:13 -07003398 // It would be unusual for this value to be negative, but check just in case ...
3399 if (signed_frames >= 0) {
3400 *frames = signed_frames;
3401 ret = 0;
3402 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003403 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303404 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3405 *frames = out->written;
3406 clock_gettime(CLOCK_MONOTONIC, timestamp);
3407 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003408 }
3409 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003410 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003411 return ret;
3412}
3413
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003414static int out_set_callback(struct audio_stream_out *stream,
3415 stream_callback_t callback, void *cookie)
3416{
3417 struct stream_out *out = (struct stream_out *)stream;
3418
3419 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003420 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003421 out->offload_callback = callback;
3422 out->offload_cookie = cookie;
3423 pthread_mutex_unlock(&out->lock);
3424 return 0;
3425}
3426
3427static int out_pause(struct audio_stream_out* stream)
3428{
3429 struct stream_out *out = (struct stream_out *)stream;
3430 int status = -ENOSYS;
3431 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003432 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003433 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003434 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303436 struct audio_device *adev = out->dev;
3437 int snd_scard_state = get_snd_card_state(adev);
3438
3439 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3440 status = compress_pause(out->compr);
3441
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003442 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003443
Mingming Yin21854652016-04-13 11:54:02 -07003444 if (audio_extn_passthru_is_active()) {
3445 ALOGV("offload use case, pause passthru");
3446 audio_extn_passthru_on_pause(out);
3447 }
3448
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303449 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003450 audio_extn_dts_notify_playback_state(out->usecase, 0,
3451 out->sample_rate, popcount(out->channel_mask),
3452 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453 }
3454 pthread_mutex_unlock(&out->lock);
3455 }
3456 return status;
3457}
3458
3459static int out_resume(struct audio_stream_out* stream)
3460{
3461 struct stream_out *out = (struct stream_out *)stream;
3462 int status = -ENOSYS;
3463 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003464 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003465 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003466 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003467 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303469 struct audio_device *adev = out->dev;
3470 int snd_scard_state = get_snd_card_state(adev);
3471
Mingming Yin21854652016-04-13 11:54:02 -07003472 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3473 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3474 pthread_mutex_lock(&out->dev->lock);
3475 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003476 pthread_mutex_unlock(&out->dev->lock);
3477 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303478 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003479 }
3480 if (!status) {
3481 out->offload_state = OFFLOAD_STATE_PLAYING;
3482 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303483 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003484 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3485 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 }
3487 pthread_mutex_unlock(&out->lock);
3488 }
3489 return status;
3490}
3491
3492static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3493{
3494 struct stream_out *out = (struct stream_out *)stream;
3495 int status = -ENOSYS;
3496 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003497 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003498 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003499 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3500 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3501 else
3502 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3503 pthread_mutex_unlock(&out->lock);
3504 }
3505 return status;
3506}
3507
3508static int out_flush(struct audio_stream_out* stream)
3509{
3510 struct stream_out *out = (struct stream_out *)stream;
3511 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003512 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003513 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003514 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003515 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3516 stop_compressed_output_l(out);
3517 out->written = 0;
3518 } else {
3519 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3520 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003521 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003522 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003523 return 0;
3524 }
3525 return -ENOSYS;
3526}
3527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528/** audio_stream_in implementation **/
3529static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3530{
3531 struct stream_in *in = (struct stream_in *)stream;
3532
3533 return in->config.rate;
3534}
3535
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003536static int in_set_sample_rate(struct audio_stream *stream __unused,
3537 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538{
3539 return -ENOSYS;
3540}
3541
3542static size_t in_get_buffer_size(const struct audio_stream *stream)
3543{
3544 struct stream_in *in = (struct stream_in *)stream;
3545
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003546 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3547 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003548 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3549 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303550 else if(audio_extn_cin_attached_usecase(in->usecase))
3551 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003552
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003553 return in->config.period_size * in->af_period_multiplier *
3554 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555}
3556
3557static uint32_t in_get_channels(const struct audio_stream *stream)
3558{
3559 struct stream_in *in = (struct stream_in *)stream;
3560
3561 return in->channel_mask;
3562}
3563
3564static audio_format_t in_get_format(const struct audio_stream *stream)
3565{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003566 struct stream_in *in = (struct stream_in *)stream;
3567
3568 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569}
3570
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003571static int in_set_format(struct audio_stream *stream __unused,
3572 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573{
3574 return -ENOSYS;
3575}
3576
3577static int in_standby(struct audio_stream *stream)
3578{
3579 struct stream_in *in = (struct stream_in *)stream;
3580 struct audio_device *adev = in->dev;
3581 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303582 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3583 stream, in->usecase, use_case_table[in->usecase]);
3584
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003585 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003586 if (!in->standby && in->is_st_session) {
3587 ALOGD("%s: sound trigger pcm stop lab", __func__);
3588 audio_extn_sound_trigger_stop_lab(in);
3589 in->standby = 1;
3590 }
3591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003593 if (adev->adm_deregister_stream)
3594 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3595
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003596 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003598 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3599 voice_extn_compress_voip_close_input_stream(stream);
3600 ALOGD("VOIP input entered standby");
3601 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303602 if (audio_extn_cin_attached_usecase(in->usecase))
3603 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003604 if (in->pcm) {
3605 pcm_close(in->pcm);
3606 in->pcm = NULL;
3607 }
3608 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003609 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003610 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 }
3612 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003613 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 return status;
3615}
3616
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003617static int in_dump(const struct audio_stream *stream __unused,
3618 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619{
3620 return 0;
3621}
3622
3623static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3624{
3625 struct stream_in *in = (struct stream_in *)stream;
3626 struct audio_device *adev = in->dev;
3627 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003629 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303631 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 parms = str_parms_create_str(kvpairs);
3633
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303634 if (!parms)
3635 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003636 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003637 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003638
3639 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3640 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 val = atoi(value);
3642 /* no audio source uses val == 0 */
3643 if ((in->source != val) && (val != 0)) {
3644 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003645 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3646 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3647 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003648 (in->config.rate == 8000 || in->config.rate == 16000 ||
3649 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003650 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003651 err = voice_extn_compress_voip_open_input_stream(in);
3652 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003653 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003654 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003655 }
3656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 }
3658 }
3659
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003660 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3661 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003663 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 in->device = val;
3665 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003666 if (!in->standby && !in->is_st_session) {
3667 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003668 if (adev->adm_on_routing_change)
3669 adev->adm_on_routing_change(adev->adm_data,
3670 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003671 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003672 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 }
3674 }
3675
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303676 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3677 if (err >= 0) {
3678 strlcpy(in->profile, value, sizeof(in->profile));
3679 ALOGV("updating stream profile with value '%s'", in->profile);
3680 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3681 &adev->streams_input_cfg_list,
3682 in->device, in->flags, in->format,
3683 in->sample_rate, in->bit_width,
3684 in->profile, &in->app_type_cfg);
3685 }
3686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003688 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689
3690 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303691error:
Eric Laurent994a6932013-07-17 11:51:42 -07003692 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 return ret;
3694}
3695
3696static char* in_get_parameters(const struct audio_stream *stream,
3697 const char *keys)
3698{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003699 struct stream_in *in = (struct stream_in *)stream;
3700 struct str_parms *query = str_parms_create_str(keys);
3701 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003702 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003703
3704 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003705 if (reply) {
3706 str_parms_destroy(reply);
3707 }
3708 if (query) {
3709 str_parms_destroy(query);
3710 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003711 ALOGE("in_get_parameters: failed to create query or reply");
3712 return NULL;
3713 }
3714
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003715 ALOGV("%s: enter: keys - %s", __func__, keys);
3716
3717 voice_extn_in_get_parameters(in, query, reply);
3718
3719 str = str_parms_to_str(reply);
3720 str_parms_destroy(query);
3721 str_parms_destroy(reply);
3722
3723 ALOGV("%s: exit: returns - %s", __func__, str);
3724 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725}
3726
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003727static int in_set_gain(struct audio_stream_in *stream __unused,
3728 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729{
3730 return 0;
3731}
3732
3733static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3734 size_t bytes)
3735{
3736 struct stream_in *in = (struct stream_in *)stream;
3737 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303738 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303739 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303740 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003742 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303743
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003744 if (in->is_st_session) {
3745 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3746 /* Read from sound trigger HAL */
3747 audio_extn_sound_trigger_read(in, buffer, bytes);
3748 pthread_mutex_unlock(&in->lock);
3749 return bytes;
3750 }
3751
Ashish Jainbbce4322016-02-16 13:25:27 +05303752 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003753 ALOGD(" %s: sound card is not active/SSR state", __func__);
3754 ret= -EIO;;
3755 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303756 }
3757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003759 pthread_mutex_lock(&adev->lock);
3760 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3761 ret = voice_extn_compress_voip_start_input_stream(in);
3762 else
3763 ret = start_input_stream(in);
3764 pthread_mutex_unlock(&adev->lock);
3765 if (ret != 0) {
3766 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 }
3768 in->standby = 0;
3769 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003771 // what's the duration requested by the client?
3772 long ns = 0;
3773
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303774 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003775 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3776 in->config.rate;
3777
3778 request_in_focus(in, ns);
3779 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003780
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303781 if (audio_extn_cin_attached_usecase(in->usecase)) {
3782 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3783 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303784 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003785 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303786 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003787 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003788 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003789 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303790 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003791 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303792 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3793 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3794 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3795 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303796 ret = -EINVAL;
3797 goto exit;
3798 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303799 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303800 ret = -errno;
3801 }
3802 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303803 /* bytes read is always set to bytes for non compress usecases */
3804 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 }
3806
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003807 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 /*
3810 * Instead of writing zeroes here, we could trust the hardware
3811 * to always provide zeroes when muted.
3812 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303813 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3814 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815 memset(buffer, 0, bytes);
3816
3817exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303818 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303819 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003820 if (-ENETRESET == ret)
3821 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 pthread_mutex_unlock(&in->lock);
3824
3825 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303826 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303827 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303828 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303829 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303830 in->standby = true;
3831 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303832 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3833 bytes_read = bytes;
3834 memset(buffer, 0, bytes);
3835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003837 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303838 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303839 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303841 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842}
3843
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003844static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845{
3846 return 0;
3847}
3848
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003849static int add_remove_audio_effect(const struct audio_stream *stream,
3850 effect_handle_t effect,
3851 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003853 struct stream_in *in = (struct stream_in *)stream;
3854 int status = 0;
3855 effect_descriptor_t desc;
3856
3857 status = (*effect)->get_descriptor(effect, &desc);
3858 if (status != 0)
3859 return status;
3860
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003861 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003862 pthread_mutex_lock(&in->dev->lock);
3863 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3864 in->enable_aec != enable &&
3865 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3866 in->enable_aec = enable;
3867 if (!in->standby)
3868 select_devices(in->dev, in->usecase);
3869 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003870 if (in->enable_ns != enable &&
3871 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3872 in->enable_ns = enable;
3873 if (!in->standby)
3874 select_devices(in->dev, in->usecase);
3875 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003876 pthread_mutex_unlock(&in->dev->lock);
3877 pthread_mutex_unlock(&in->lock);
3878
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 return 0;
3880}
3881
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003882static int in_add_audio_effect(const struct audio_stream *stream,
3883 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884{
Eric Laurent994a6932013-07-17 11:51:42 -07003885 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003886 return add_remove_audio_effect(stream, effect, true);
3887}
3888
3889static int in_remove_audio_effect(const struct audio_stream *stream,
3890 effect_handle_t effect)
3891{
Eric Laurent994a6932013-07-17 11:51:42 -07003892 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003893 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894}
3895
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303896int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 audio_io_handle_t handle,
3898 audio_devices_t devices,
3899 audio_output_flags_t flags,
3900 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003901 struct audio_stream_out **stream_out,
3902 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903{
3904 struct audio_device *adev = (struct audio_device *)dev;
3905 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303906 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003907 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303910
3911 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3912 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003913 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303914 return -EINVAL;
3915 }
3916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3918
Mingming Yin3a941d42016-02-17 18:08:05 -08003919 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3920 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303921 devices, flags, &out->stream);
3922
3923
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003924 if (!out) {
3925 return -ENOMEM;
3926 }
3927
Haynes Mathew George204045b2015-02-25 20:32:03 -08003928 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003929 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003930 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932 if (devices == AUDIO_DEVICE_NONE)
3933 devices = AUDIO_DEVICE_OUT_SPEAKER;
3934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935 out->flags = flags;
3936 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003937 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003938 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939 out->sample_rate = config->sample_rate;
3940 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3941 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003942 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003943 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003944 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303945 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946
Mingming Yin3a941d42016-02-17 18:08:05 -08003947 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3948 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3949 pthread_mutex_lock(&adev->lock);
3950 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3951 ret = read_hdmi_sink_caps(out);
3952 pthread_mutex_unlock(&adev->lock);
3953 if (ret != 0) {
3954 if (ret == -ENOSYS) {
3955 /* ignore and go with default */
3956 ret = 0;
3957 } else {
3958 ALOGE("error reading hdmi sink caps");
3959 goto error_open;
3960 }
3961 }
3962 }
3963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303965 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003966 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003967 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003968 ret = voice_extn_compress_voip_open_output_stream(out);
3969 if (ret != 0) {
3970 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3971 __func__, ret);
3972 goto error_open;
3973 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003974 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05303975 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003976
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003977 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3978 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3979 ALOGE("%s: Unsupported Offload information", __func__);
3980 ret = -EINVAL;
3981 goto error_open;
3982 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003983
Mingming Yin3a941d42016-02-17 18:08:05 -08003984 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003985 if(config->offload_info.format == 0)
3986 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003987 if (config->offload_info.sample_rate == 0)
3988 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003989 }
3990
Mingming Yin90310102013-11-13 16:57:00 -08003991 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303992 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003993 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003994 ret = -EINVAL;
3995 goto error_open;
3996 }
3997
3998 out->compr_config.codec = (struct snd_codec *)
3999 calloc(1, sizeof(struct snd_codec));
4000
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004001 if (!out->compr_config.codec) {
4002 ret = -ENOMEM;
4003 goto error_open;
4004 }
4005
Dhananjay Kumarac341582017-02-23 23:42:25 +05304006 out->stream.pause = out_pause;
4007 out->stream.resume = out_resume;
4008 out->stream.flush = out_flush;
4009 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004010 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004011 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304012 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004013 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304014 } else {
4015 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4016 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004017 }
vivek mehta446c3962015-09-14 10:57:35 -07004018
4019 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004020 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4021 config->format == 0 && config->sample_rate == 0 &&
4022 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004023 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004024 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4025 } else {
4026 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4027 ret = -EEXIST;
4028 goto error_open;
4029 }
vivek mehta446c3962015-09-14 10:57:35 -07004030 }
4031
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004032 if (config->offload_info.channel_mask)
4033 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004034 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004035 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004036 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004037 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304038 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004039 ret = -EINVAL;
4040 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004041 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004042
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004043 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004044 out->sample_rate = config->offload_info.sample_rate;
4045
Mingming Yin3ee55c62014-08-04 14:23:35 -07004046 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004047
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304048 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4049 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4050 audio_extn_dolby_send_ddp_endp_params(adev);
4051 audio_extn_dolby_set_dmid(adev);
4052 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004054 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004055 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004056 out->compr_config.codec->bit_rate =
4057 config->offload_info.bit_rate;
4058 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304059 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004060 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304061 /* Update bit width only for non passthrough usecases.
4062 * For passthrough usecases, the output will always be opened @16 bit
4063 */
4064 if (!audio_extn_passthru_is_passthrough_stream(out))
4065 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004066 /*TODO: Do we need to change it for passthrough */
4067 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004068
Manish Dewangana6fc5442015-08-24 20:30:31 +05304069 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4070 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304071 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304072 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304073 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4074 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304075
4076 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4077 AUDIO_FORMAT_PCM) {
4078
4079 /*Based on platform support, configure appropriate alsa format for corresponding
4080 *hal input format.
4081 */
4082 out->compr_config.codec->format = hal_format_to_alsa(
4083 config->offload_info.format);
4084
Ashish Jain83a6cc22016-06-28 14:34:17 +05304085 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304086 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304087 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304088
Dhananjay Kumarac341582017-02-23 23:42:25 +05304089 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304090 *hal input format and alsa format might differ based on platform support.
4091 */
4092 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304093 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304094
4095 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4096
4097 /* Check if alsa session is configured with the same format as HAL input format,
4098 * if not then derive correct fragment size needed to accomodate the
4099 * conversion of HAL input format to alsa format.
4100 */
4101 audio_extn_utils_update_direct_pcm_fragment_size(out);
4102
4103 /*if hal input and output fragment size is different this indicates HAL input format is
4104 *not same as the alsa format
4105 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304106 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304107 /*Allocate a buffer to convert input data to the alsa configured format.
4108 *size of convert buffer is equal to the size required to hold one fragment size
4109 *worth of pcm data, this is because flinger does not write more than fragment_size
4110 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304111 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4112 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304113 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4114 ret = -ENOMEM;
4115 goto error_open;
4116 }
4117 }
4118 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4119 out->compr_config.fragment_size =
4120 audio_extn_passthru_get_buffer_size(&config->offload_info);
4121 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4122 } else {
4123 out->compr_config.fragment_size =
4124 platform_get_compress_offload_buffer_size(&config->offload_info);
4125 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4126 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004127
Amit Shekhar6f461b12014-08-01 14:52:58 -07004128 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304129 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004130
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304131 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4132 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4133 }
4134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004135 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4136 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004137
Manish Dewangan69426c82017-01-30 17:35:36 +05304138 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4139 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4140 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4141 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4142 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4143 } else {
4144 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4145 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004146
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004147 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304148 out->send_next_track_params = false;
4149 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004150 out->offload_state = OFFLOAD_STATE_IDLE;
4151 out->playback_started = 0;
4152
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004153 audio_extn_dts_create_state_notifier_node(out->usecase);
4154
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004155 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4156 __func__, config->offload_info.version,
4157 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304158
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304159 /* Check if DSD audio format is supported in codec
4160 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304161 */
4162
4163 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304164 (!platform_check_codec_dsd_support(adev->platform) ||
4165 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304166 ret = -EINVAL;
4167 goto error_open;
4168 }
4169
Ashish Jain5106d362016-05-11 19:23:33 +05304170 /* Disable gapless if any of the following is true
4171 * passthrough playback
4172 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304173 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304174 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304175 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304176 (config->format == AUDIO_FORMAT_DSD) ||
4177 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304178 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304179 check_and_set_gapless_mode(adev, false);
4180 } else
4181 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004182
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304183 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004184 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4185 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304186 if (config->format == AUDIO_FORMAT_DSD) {
4187 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4188 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4189 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004190
4191 create_offload_callback_thread(out);
4192
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004193 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304194 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004195 if (ret != 0) {
4196 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4197 __func__, ret);
4198 goto error_open;
4199 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004200 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4201 if (config->sample_rate == 0)
4202 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4203 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4204 config->sample_rate != 8000) {
4205 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4206 ret = -EINVAL;
4207 goto error_open;
4208 }
4209 out->sample_rate = config->sample_rate;
4210 out->config.rate = config->sample_rate;
4211 if (config->format == AUDIO_FORMAT_DEFAULT)
4212 config->format = AUDIO_FORMAT_PCM_16_BIT;
4213 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4214 config->format = AUDIO_FORMAT_PCM_16_BIT;
4215 ret = -EINVAL;
4216 goto error_open;
4217 }
4218 out->format = config->format;
4219 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4220 out->config = pcm_config_afe_proxy_playback;
4221 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004222 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304223 unsigned int channels = 0;
4224 /*Update config params to default if not set by the caller*/
4225 if (config->sample_rate == 0)
4226 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4227 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4228 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4229 if (config->format == AUDIO_FORMAT_DEFAULT)
4230 config->format = AUDIO_FORMAT_PCM_16_BIT;
4231
4232 channels = audio_channel_count_from_out_mask(out->channel_mask);
4233
Ashish Jain83a6cc22016-06-28 14:34:17 +05304234 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4235 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004236 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4237 out->flags);
4238 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304239 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4240 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4241 out->config = pcm_config_low_latency;
4242 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4243 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4244 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304245 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4246 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4247 if (out->config.period_size <= 0) {
4248 ALOGE("Invalid configuration period size is not valid");
4249 ret = -EINVAL;
4250 goto error_open;
4251 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304252 } else {
4253 /* primary path is the default path selected if no other outputs are available/suitable */
4254 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4255 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4256 }
4257 out->hal_ip_format = format = out->format;
4258 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4259 out->hal_op_format = pcm_format_to_hal(out->config.format);
4260 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4261 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004262 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304263 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304264 if (out->hal_ip_format != out->hal_op_format) {
4265 uint32_t buffer_size = out->config.period_size *
4266 format_to_bitwidth_table[out->hal_op_format] *
4267 out->config.channels;
4268 out->convert_buffer = calloc(1, buffer_size);
4269 if (out->convert_buffer == NULL){
4270 ALOGE("Allocation failed for convert buffer for size %d",
4271 out->compr_config.fragment_size);
4272 ret = -ENOMEM;
4273 goto error_open;
4274 }
4275 ALOGD("Convert buffer allocated of size %d", buffer_size);
4276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004277 }
4278
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004279 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4280 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304281
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004282 /* TODO remove this hardcoding and check why width is zero*/
4283 if (out->bit_width == 0)
4284 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304285 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004286 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304287 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304288 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304289 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004290 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4291 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4292 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004293 if(adev->primary_output == NULL)
4294 adev->primary_output = out;
4295 else {
4296 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004297 ret = -EEXIST;
4298 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004299 }
4300 }
4301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 /* Check if this usecase is already existing */
4303 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004304 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4305 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004308 ret = -EEXIST;
4309 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004312 pthread_mutex_unlock(&adev->lock);
4313
4314 out->stream.common.get_sample_rate = out_get_sample_rate;
4315 out->stream.common.set_sample_rate = out_set_sample_rate;
4316 out->stream.common.get_buffer_size = out_get_buffer_size;
4317 out->stream.common.get_channels = out_get_channels;
4318 out->stream.common.get_format = out_get_format;
4319 out->stream.common.set_format = out_set_format;
4320 out->stream.common.standby = out_standby;
4321 out->stream.common.dump = out_dump;
4322 out->stream.common.set_parameters = out_set_parameters;
4323 out->stream.common.get_parameters = out_get_parameters;
4324 out->stream.common.add_audio_effect = out_add_audio_effect;
4325 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4326 out->stream.get_latency = out_get_latency;
4327 out->stream.set_volume = out_set_volume;
4328 out->stream.write = out_write;
4329 out->stream.get_render_position = out_get_render_position;
4330 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004331 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004333 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004335 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004336 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337
4338 config->format = out->stream.common.get_format(&out->stream.common);
4339 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4340 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4341
4342 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304343 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004344 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004345
4346 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4347 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4348 popcount(out->channel_mask), out->playback_started);
4349
Eric Laurent994a6932013-07-17 11:51:42 -07004350 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004352
4353error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304354 if (out->convert_buffer)
4355 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004356 free(out);
4357 *stream_out = NULL;
4358 ALOGD("%s: exit: ret %d", __func__, ret);
4359 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360}
4361
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304362void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363 struct audio_stream_out *stream)
4364{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004365 struct stream_out *out = (struct stream_out *)stream;
4366 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004367 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004368
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304369 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4370
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004371 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304372 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004373 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304374 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004375 if(ret != 0)
4376 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4377 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004378 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004379 out_standby(&stream->common);
4380
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004381 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004382 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004383 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004384 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004385 if (out->compr_config.codec != NULL)
4386 free(out->compr_config.codec);
4387 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004388
Ashish Jain83a6cc22016-06-28 14:34:17 +05304389 if (out->convert_buffer != NULL) {
4390 free(out->convert_buffer);
4391 out->convert_buffer = NULL;
4392 }
4393
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004394 if (adev->voice_tx_output == out)
4395 adev->voice_tx_output = NULL;
4396
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304397 if (adev->primary_output == out)
4398 adev->primary_output = NULL;
4399
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004400 pthread_cond_destroy(&out->cond);
4401 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004403 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004404}
4405
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004406static void close_compress_sessions(struct audio_device *adev)
4407{
Mingming Yin7b762e72015-03-04 13:47:32 -08004408 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304409 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004410 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004411 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304412
4413 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004414 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304415 if (is_offload_usecase(usecase->id)) {
4416 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004417 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4418 out = usecase->stream.out;
4419 pthread_mutex_unlock(&adev->lock);
4420 out_standby(&out->stream.common);
4421 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004422 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004423 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304424 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004425 }
4426 pthread_mutex_unlock(&adev->lock);
4427}
4428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4430{
4431 struct audio_device *adev = (struct audio_device *)dev;
4432 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004434 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004435 int ret;
4436 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004438 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304441 if (!parms)
4442 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004443 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4444 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304445 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304446 if (strstr(snd_card_status, "OFFLINE")) {
4447 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304448 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004449 //close compress sessions on OFFLINE status
4450 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304451 } else if (strstr(snd_card_status, "ONLINE")) {
4452 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304453 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004454 //send dts hpx license if enabled
4455 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304456 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304457 }
4458
4459 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004460 status = voice_set_parameters(adev, parms);
4461 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004462 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004464 status = platform_set_parameters(adev->platform, parms);
4465 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004466 goto done;
4467
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004468 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4469 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004470 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4472 adev->bluetooth_nrec = true;
4473 else
4474 adev->bluetooth_nrec = false;
4475 }
4476
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004477 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4478 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4480 adev->screen_off = false;
4481 else
4482 adev->screen_off = true;
4483 }
4484
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004485 ret = str_parms_get_int(parms, "rotation", &val);
4486 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004487 bool reverse_speakers = false;
4488 switch(val) {
4489 // FIXME: note that the code below assumes that the speakers are in the correct placement
4490 // relative to the user when the device is rotated 90deg from its default rotation. This
4491 // assumption is device-specific, not platform-specific like this code.
4492 case 270:
4493 reverse_speakers = true;
4494 break;
4495 case 0:
4496 case 90:
4497 case 180:
4498 break;
4499 default:
4500 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004501 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004502 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004503 if (status == 0) {
4504 if (adev->speaker_lr_swap != reverse_speakers) {
4505 adev->speaker_lr_swap = reverse_speakers;
4506 // only update the selected device if there is active pcm playback
4507 struct audio_usecase *usecase;
4508 struct listnode *node;
4509 list_for_each(node, &adev->usecase_list) {
4510 usecase = node_to_item(node, struct audio_usecase, list);
4511 if (usecase->type == PCM_PLAYBACK) {
4512 select_devices(adev, usecase->id);
4513 break;
4514 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004515 }
4516 }
4517 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004518 }
4519
Mingming Yin514a8bc2014-07-29 15:22:21 -07004520 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4521 if (ret >= 0) {
4522 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4523 adev->bt_wb_speech_enabled = true;
4524 else
4525 adev->bt_wb_speech_enabled = false;
4526 }
4527
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004528 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4529 if (ret >= 0) {
4530 val = atoi(value);
4531 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004532 ALOGV("cache new ext disp type and edid");
4533 ret = platform_get_ext_disp_type(adev->platform);
4534 if (ret < 0) {
4535 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004536 status = ret;
4537 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004538 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004539 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004540 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004541 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004542 /*
4543 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4544 * Per AudioPolicyManager, USB device is higher priority than WFD.
4545 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4546 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4547 * starting voice call on USB
4548 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004549 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4550 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004551 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4552 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004553 }
vivek mehta344576a2016-04-12 18:56:03 -07004554 ALOGV("detected USB connect .. disable proxy");
4555 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004556 }
4557 }
4558
4559 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4560 if (ret >= 0) {
4561 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004562 /*
4563 * The HDMI / Displayport disconnect handling has been moved to
4564 * audio extension to ensure that its parameters are not
4565 * invalidated prior to updating sysfs of the disconnect event
4566 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4567 */
4568 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004569 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004570 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4571 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304572 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4573 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004574 }
vivek mehta344576a2016-04-12 18:56:03 -07004575 ALOGV("detected USB disconnect .. enable proxy");
4576 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004577 }
4578 }
4579
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304580 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4581 if (ret >= 0) {
4582 struct audio_usecase *usecase;
4583 struct listnode *node;
4584 list_for_each(node, &adev->usecase_list) {
4585 usecase = node_to_item(node, struct audio_usecase, list);
4586 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004587 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304588 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304589 lock_output_stream(usecase->stream.out);
4590 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304591 //force device switch to re configure encoder
4592 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304593 audio_extn_a2dp_set_handoff_mode(false);
4594 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304595 break;
4596 }
4597 }
4598 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004599
4600 //handle vr audio setparam
4601 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4602 value, sizeof(value));
4603 if (ret >= 0) {
4604 ALOGI("Setting vr mode to be %s", value);
4605 if (!strncmp(value, "true", 4)) {
4606 adev->vr_audio_mode_enabled = true;
4607 ALOGI("Setting vr mode to true");
4608 } else if (!strncmp(value, "false", 5)) {
4609 adev->vr_audio_mode_enabled = false;
4610 ALOGI("Setting vr mode to false");
4611 } else {
4612 ALOGI("wrong vr mode set");
4613 }
4614 }
4615
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304616 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004617done:
4618 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004619 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304620error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004621 ALOGV("%s: exit with code(%d)", __func__, status);
4622 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623}
4624
4625static char* adev_get_parameters(const struct audio_hw_device *dev,
4626 const char *keys)
4627{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004628 struct audio_device *adev = (struct audio_device *)dev;
4629 struct str_parms *reply = str_parms_create();
4630 struct str_parms *query = str_parms_create_str(keys);
4631 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304632 char value[256] = {0};
4633 int ret = 0;
4634
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004635 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004636 if (reply) {
4637 str_parms_destroy(reply);
4638 }
4639 if (query) {
4640 str_parms_destroy(query);
4641 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004642 ALOGE("adev_get_parameters: failed to create query or reply");
4643 return NULL;
4644 }
4645
Naresh Tannirud7205b62014-06-20 02:54:48 +05304646 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4647 sizeof(value));
4648 if (ret >=0) {
4649 int val = 1;
4650 pthread_mutex_lock(&adev->snd_card_status.lock);
4651 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4652 val = 0;
4653 pthread_mutex_unlock(&adev->snd_card_status.lock);
4654 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4655 goto exit;
4656 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004657 //handle vr audio getparam
4658
4659 ret = str_parms_get_str(query,
4660 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4661 value, sizeof(value));
4662
4663 if (ret >= 0) {
4664 bool vr_audio_enabled = false;
4665 pthread_mutex_lock(&adev->lock);
4666 vr_audio_enabled = adev->vr_audio_mode_enabled;
4667 pthread_mutex_unlock(&adev->lock);
4668
4669 ALOGI("getting vr mode to %d", vr_audio_enabled);
4670
4671 if (vr_audio_enabled) {
4672 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4673 "true");
4674 goto exit;
4675 } else {
4676 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4677 "false");
4678 goto exit;
4679 }
4680 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004681
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004682 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004683 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004684 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004685 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304686 pthread_mutex_unlock(&adev->lock);
4687
Naresh Tannirud7205b62014-06-20 02:54:48 +05304688exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004689 str = str_parms_to_str(reply);
4690 str_parms_destroy(query);
4691 str_parms_destroy(reply);
4692
4693 ALOGV("%s: exit: returns - %s", __func__, str);
4694 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695}
4696
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004697static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698{
4699 return 0;
4700}
4701
4702static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4703{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004704 int ret;
4705 struct audio_device *adev = (struct audio_device *)dev;
4706 pthread_mutex_lock(&adev->lock);
4707 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004708 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004709 pthread_mutex_unlock(&adev->lock);
4710 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711}
4712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004713static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4714 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004715{
4716 return -ENOSYS;
4717}
4718
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004719static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4720 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721{
4722 return -ENOSYS;
4723}
4724
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004725static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4726 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004727{
4728 return -ENOSYS;
4729}
4730
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004731static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4732 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733{
4734 return -ENOSYS;
4735}
4736
4737static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4738{
4739 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741 pthread_mutex_lock(&adev->lock);
4742 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004743 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004745 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004746 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004747 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004748 adev->current_call_output = NULL;
4749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750 }
4751 pthread_mutex_unlock(&adev->lock);
4752 return 0;
4753}
4754
4755static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4756{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004757 int ret;
4758
4759 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004760 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004761 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4762 pthread_mutex_unlock(&adev->lock);
4763
4764 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765}
4766
4767static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4768{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004769 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770 return 0;
4771}
4772
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004773static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 const struct audio_config *config)
4775{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004776 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004777
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004778 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4779 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780}
4781
4782static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004783 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784 audio_devices_t devices,
4785 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004786 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304787 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004788 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004789 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790{
4791 struct audio_device *adev = (struct audio_device *)dev;
4792 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004793 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004794 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004795 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304796 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304799 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4800 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304802 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004803
4804 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004805
4806 if (!in) {
4807 ALOGE("failed to allocate input stream");
4808 return -ENOMEM;
4809 }
4810
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304811 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304812 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4813 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004814 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004815 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 in->stream.common.get_sample_rate = in_get_sample_rate;
4818 in->stream.common.set_sample_rate = in_set_sample_rate;
4819 in->stream.common.get_buffer_size = in_get_buffer_size;
4820 in->stream.common.get_channels = in_get_channels;
4821 in->stream.common.get_format = in_get_format;
4822 in->stream.common.set_format = in_set_format;
4823 in->stream.common.standby = in_standby;
4824 in->stream.common.dump = in_dump;
4825 in->stream.common.set_parameters = in_set_parameters;
4826 in->stream.common.get_parameters = in_get_parameters;
4827 in->stream.common.add_audio_effect = in_add_audio_effect;
4828 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4829 in->stream.set_gain = in_set_gain;
4830 in->stream.read = in_read;
4831 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4832
4833 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004834 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004836 in->standby = 1;
4837 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004838 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004839 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304841 in->usecase = USECASE_AUDIO_RECORD;
4842 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4843 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4844 is_low_latency = true;
4845#if LOW_LATENCY_CAPTURE_USE_CASE
4846 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4847#endif
4848 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4849 }
4850
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004851 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004852 if (in->realtime) {
4853 in->config = pcm_config_audio_capture_rt;
4854 in->sample_rate = in->config.rate;
4855 in->af_period_multiplier = af_period_multiplier;
4856 } else {
4857 in->config = pcm_config_audio_capture;
4858 in->config.rate = config->sample_rate;
4859 in->sample_rate = config->sample_rate;
4860 in->af_period_multiplier = 1;
4861 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304862 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304864 /* restrict 24 bit capture for unprocessed source only
4865 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4866 */
4867 if (config->format == AUDIO_FORMAT_DEFAULT) {
4868 config->format = AUDIO_FORMAT_PCM_16_BIT;
4869 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4870 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4871 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4872 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4873 bool ret_error = false;
4874 in->bit_width = 24;
4875 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4876 from HAL is 24_packed and 8_24
4877 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4878 24_packed return error indicating supported format is 24_packed
4879 *> In case of any other source requesting 24 bit or float return error
4880 indicating format supported is 16 bit only.
4881
4882 on error flinger will retry with supported format passed
4883 */
4884 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4885 (source != AUDIO_SOURCE_CAMCORDER)) {
4886 config->format = AUDIO_FORMAT_PCM_16_BIT;
4887 if (config->sample_rate > 48000)
4888 config->sample_rate = 48000;
4889 ret_error = true;
4890 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4891 in->config.format = PCM_FORMAT_S24_3LE;
4892 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4893 in->config.format = PCM_FORMAT_S24_LE;
4894 } else {
4895 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4896 ret_error = true;
4897 }
4898
4899 if (ret_error) {
4900 ret = -EINVAL;
4901 goto err_open;
4902 }
4903 }
4904
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304905 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304906 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4907 (adev->mode != AUDIO_MODE_IN_CALL)) {
4908 ret = -EINVAL;
4909 goto err_open;
4910 }
4911
4912 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4913 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004914 if (config->sample_rate == 0)
4915 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4916 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4917 config->sample_rate != 8000) {
4918 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4919 ret = -EINVAL;
4920 goto err_open;
4921 }
4922 if (config->format == AUDIO_FORMAT_DEFAULT)
4923 config->format = AUDIO_FORMAT_PCM_16_BIT;
4924 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4925 config->format = AUDIO_FORMAT_PCM_16_BIT;
4926 ret = -EINVAL;
4927 goto err_open;
4928 }
4929
4930 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4931 in->config = pcm_config_afe_proxy_record;
4932 in->config.channels = channel_count;
4933 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304934 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304935 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4936 in, config, &channel_mask_updated)) {
4937 if (channel_mask_updated == true) {
4938 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4939 __func__, config->channel_mask);
4940 ret = -EINVAL;
4941 goto err_open;
4942 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304943 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004944 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004945 audio_extn_compr_cap_format_supported(config->format) &&
4946 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004947 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304948 } else if (audio_extn_cin_applicable_stream(in)) {
4949 ret = audio_extn_cin_configure_input_stream(in);
4950 if (ret)
4951 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004952 } else {
4953 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004954 if (!in->realtime) {
4955 in->format = config->format;
4956 frame_size = audio_stream_in_frame_size(&in->stream);
4957 buffer_size = get_input_buffer_size(config->sample_rate,
4958 config->format,
4959 channel_count,
4960 is_low_latency);
4961 in->config.period_size = buffer_size / frame_size;
4962 }
4963
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004964 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004965 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004966 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004967 (in->config.rate == 8000 || in->config.rate == 16000 ||
4968 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004969 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4970 voice_extn_compress_voip_open_input_stream(in);
4971 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004972 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004973
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304974 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4975 &adev->streams_input_cfg_list,
4976 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304977 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304978
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004979 /* This stream could be for sound trigger lab,
4980 get sound trigger pcm if present */
4981 audio_extn_sound_trigger_check_and_get_session(in);
4982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004984 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004985 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004986
4987err_open:
4988 free(in);
4989 *stream_in = NULL;
4990 return ret;
4991}
4992
4993static void adev_close_input_stream(struct audio_hw_device *dev,
4994 struct audio_stream_in *stream)
4995{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004996 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004997 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004998 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304999
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305000 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005001
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305002 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005003 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305004
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005005 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305006 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005007 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305008 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005009 if (ret != 0)
5010 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5011 __func__, ret);
5012 } else
5013 in_standby(&stream->common);
5014
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005015 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005016 audio_extn_ssr_deinit();
5017 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005018
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305019 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005020 audio_extn_compr_cap_format_supported(in->config.format))
5021 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305022
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305023 if (audio_extn_cin_attached_usecase(in->usecase))
5024 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005025
Mingming Yinfd7607b2016-01-22 12:48:44 -08005026 if (in->is_st_session) {
5027 ALOGV("%s: sound trigger pcm stop lab", __func__);
5028 audio_extn_sound_trigger_stop_lab(in);
5029 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005030 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031 return;
5032}
5033
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005034static int adev_dump(const audio_hw_device_t *device __unused,
5035 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036{
5037 return 0;
5038}
5039
5040static int adev_close(hw_device_t *device)
5041{
5042 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005043
5044 if (!adev)
5045 return 0;
5046
5047 pthread_mutex_lock(&adev_init_lock);
5048
5049 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005050 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005051 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305052 audio_extn_utils_release_streams_cfg_lists(
5053 &adev->streams_output_cfg_list,
5054 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305055 if (audio_extn_qaf_is_enabled())
5056 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005057 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005058 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005059 free(adev->snd_dev_ref_cnt);
5060 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005061 if (adev->adm_deinit)
5062 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305063 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005064 free(device);
5065 adev = NULL;
5066 }
5067 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005068
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005069 return 0;
5070}
5071
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005072/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5073 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5074 * just that it _might_ work.
5075 */
5076static int period_size_is_plausible_for_low_latency(int period_size)
5077{
5078 switch (period_size) {
5079 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005080 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005081 case 240:
5082 case 320:
5083 case 480:
5084 return 1;
5085 default:
5086 return 0;
5087 }
5088}
5089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005090static int adev_open(const hw_module_t *module, const char *name,
5091 hw_device_t **device)
5092{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305093 int ret;
5094
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005095 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5097
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005098 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005099 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005100 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005101 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005102 ALOGD("%s: returning existing instance of adev", __func__);
5103 ALOGD("%s: exit", __func__);
5104 pthread_mutex_unlock(&adev_init_lock);
5105 return 0;
5106 }
5107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108 adev = calloc(1, sizeof(struct audio_device));
5109
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005110 if (!adev) {
5111 pthread_mutex_unlock(&adev_init_lock);
5112 return -ENOMEM;
5113 }
5114
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005115 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005117 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5118 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5119 adev->device.common.module = (struct hw_module_t *)module;
5120 adev->device.common.close = adev_close;
5121
5122 adev->device.init_check = adev_init_check;
5123 adev->device.set_voice_volume = adev_set_voice_volume;
5124 adev->device.set_master_volume = adev_set_master_volume;
5125 adev->device.get_master_volume = adev_get_master_volume;
5126 adev->device.set_master_mute = adev_set_master_mute;
5127 adev->device.get_master_mute = adev_get_master_mute;
5128 adev->device.set_mode = adev_set_mode;
5129 adev->device.set_mic_mute = adev_set_mic_mute;
5130 adev->device.get_mic_mute = adev_get_mic_mute;
5131 adev->device.set_parameters = adev_set_parameters;
5132 adev->device.get_parameters = adev_get_parameters;
5133 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5134 adev->device.open_output_stream = adev_open_output_stream;
5135 adev->device.close_output_stream = adev_close_output_stream;
5136 adev->device.open_input_stream = adev_open_input_stream;
5137 adev->device.close_input_stream = adev_close_input_stream;
5138 adev->device.dump = adev_dump;
5139
5140 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005142 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005143 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005144 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005145 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005146 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005147 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005148 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005149 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005150 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005151 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005152 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005153 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305154 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305155 adev->perf_lock_opts[0] = 0x101;
5156 adev->perf_lock_opts[1] = 0x20E;
5157 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305158
5159 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5160 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005161 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005162 adev->platform = platform_init(adev);
5163 if (!adev->platform) {
5164 free(adev->snd_dev_ref_cnt);
5165 free(adev);
5166 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5167 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005168 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305169 pthread_mutex_destroy(&adev->lock);
5170 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005171 return -EINVAL;
5172 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005173
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305174 if (audio_extn_qaf_is_enabled()) {
5175 ret = audio_extn_qaf_init(adev);
5176 if (ret < 0) {
5177 free(adev);
5178 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5179 *device = NULL;
5180 pthread_mutex_unlock(&adev_init_lock);
5181 pthread_mutex_destroy(&adev->lock);
5182 return ret;
5183 }
5184
5185 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5186 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5187 }
5188
Naresh Tanniru4c630392014-05-12 01:05:52 +05305189 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5190
Eric Laurentc4aef752013-09-12 17:45:53 -07005191 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5192 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5193 if (adev->visualizer_lib == NULL) {
5194 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5195 } else {
5196 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5197 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005198 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005199 "visualizer_hal_start_output");
5200 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005201 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005202 "visualizer_hal_stop_output");
5203 }
5204 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305205 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005206 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005207 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005208 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005209
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005210 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5211 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5212 if (adev->offload_effects_lib == NULL) {
5213 ALOGE("%s: DLOPEN failed for %s", __func__,
5214 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5215 } else {
5216 ALOGV("%s: DLOPEN successful for %s", __func__,
5217 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5218 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305219 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005220 "offload_effects_bundle_hal_start_output");
5221 adev->offload_effects_stop_output =
5222 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5223 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005224 adev->offload_effects_set_hpx_state =
5225 (int (*)(bool))dlsym(adev->offload_effects_lib,
5226 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305227 adev->offload_effects_get_parameters =
5228 (void (*)(struct str_parms *, struct str_parms *))
5229 dlsym(adev->offload_effects_lib,
5230 "offload_effects_bundle_get_parameters");
5231 adev->offload_effects_set_parameters =
5232 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5233 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005234 }
5235 }
5236
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005237 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5238 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5239 if (adev->adm_lib == NULL) {
5240 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5241 } else {
5242 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5243 adev->adm_init = (adm_init_t)
5244 dlsym(adev->adm_lib, "adm_init");
5245 adev->adm_deinit = (adm_deinit_t)
5246 dlsym(adev->adm_lib, "adm_deinit");
5247 adev->adm_register_input_stream = (adm_register_input_stream_t)
5248 dlsym(adev->adm_lib, "adm_register_input_stream");
5249 adev->adm_register_output_stream = (adm_register_output_stream_t)
5250 dlsym(adev->adm_lib, "adm_register_output_stream");
5251 adev->adm_deregister_stream = (adm_deregister_stream_t)
5252 dlsym(adev->adm_lib, "adm_deregister_stream");
5253 adev->adm_request_focus = (adm_request_focus_t)
5254 dlsym(adev->adm_lib, "adm_request_focus");
5255 adev->adm_abandon_focus = (adm_abandon_focus_t)
5256 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005257 adev->adm_set_config = (adm_set_config_t)
5258 dlsym(adev->adm_lib, "adm_set_config");
5259 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5260 dlsym(adev->adm_lib, "adm_request_focus_v2");
5261 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5262 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5263 adev->adm_on_routing_change = (adm_on_routing_change_t)
5264 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005265 }
5266 }
5267
Mingming Yin514a8bc2014-07-29 15:22:21 -07005268 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005269 //initialize this to false for now,
5270 //this will be set to true through set param
5271 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005272
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005273 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005274 *device = &adev->device.common;
5275
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305276 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5277 &adev->streams_output_cfg_list,
5278 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005279
Kiran Kandi910e1862013-10-29 13:29:42 -07005280 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005281
5282 char value[PROPERTY_VALUE_MAX];
5283 int trial;
5284 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5285 trial = atoi(value);
5286 if (period_size_is_plausible_for_low_latency(trial)) {
5287 pcm_config_low_latency.period_size = trial;
5288 pcm_config_low_latency.start_threshold = trial / 4;
5289 pcm_config_low_latency.avail_min = trial / 4;
5290 configured_low_latency_capture_period_size = trial;
5291 }
5292 }
5293 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5294 trial = atoi(value);
5295 if (period_size_is_plausible_for_low_latency(trial)) {
5296 configured_low_latency_capture_period_size = trial;
5297 }
5298 }
5299
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005300 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5301 af_period_multiplier = atoi(value);
5302 if (af_period_multiplier < 0)
5303 af_period_multiplier = 2;
5304 else if (af_period_multiplier > 4)
5305 af_period_multiplier = 4;
5306
5307 ALOGV("new period_multiplier = %d", af_period_multiplier);
5308 }
5309
vivek mehta446c3962015-09-14 10:57:35 -07005310 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005311 pthread_mutex_unlock(&adev_init_lock);
5312
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005313 if (adev->adm_init)
5314 adev->adm_data = adev->adm_init();
5315
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305316 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305317 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005318 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005319 return 0;
5320}
5321
5322static struct hw_module_methods_t hal_module_methods = {
5323 .open = adev_open,
5324};
5325
5326struct audio_module HAL_MODULE_INFO_SYM = {
5327 .common = {
5328 .tag = HARDWARE_MODULE_TAG,
5329 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5330 .hal_api_version = HARDWARE_HAL_API_VERSION,
5331 .id = AUDIO_HARDWARE_MODULE_ID,
5332 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005333 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334 .methods = &hal_module_methods,
5335 },
5336};