blob: 7b69ca2f6246627a62278f75a88b41d015e0ad0d [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];
Manish Dewangan58229382017-02-02 15:48:41 +0530713 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714
715 if (usecase == NULL)
716 return -EINVAL;
717
718 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
719
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800720 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800722 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700723 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800724
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800725#ifdef DS1_DOLBY_DAP_ENABLED
726 audio_extn_dolby_set_dmid(adev);
727 audio_extn_dolby_set_endpoint(adev);
728#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700729 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700730 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530731 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700732 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530733 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530734 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
735 out = usecase->stream.out;
736 if (out && out->compr)
737 audio_extn_utils_compress_set_clk_rec_mode(usecase);
738 }
739
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800740 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700741 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700742 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700743 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744 ALOGV("%s: exit", __func__);
745 return 0;
746}
747
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700748int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700749 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700752 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800753
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530754 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800755 return -EINVAL;
756
757 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700758 if (usecase->type == PCM_CAPTURE)
759 snd_device = usecase->in_snd_device;
760 else
761 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800762 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700763 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700764 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700765 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700766 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530767 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 ALOGV("%s: exit", __func__);
769 return 0;
770}
771
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700772int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700773 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800774{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530775 int i, num_devices = 0;
776 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700777 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
778
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800779 if (snd_device < SND_DEVICE_MIN ||
780 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800781 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800782 return -EINVAL;
783 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700784
785 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700786
787 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
788 ALOGE("%s: Invalid sound device returned", __func__);
789 return -EINVAL;
790 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700791 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700792 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700793 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700794 return 0;
795 }
796
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530797
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700798 if (audio_extn_spkr_prot_is_enabled())
799 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700800
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800801 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
802 audio_extn_spkr_prot_is_enabled()) {
803 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700804 adev->snd_dev_ref_cnt[snd_device]--;
805 return -EINVAL;
806 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200807 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800808 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800809 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200810 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800811 return -EINVAL;
812 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700813 } else if (platform_split_snd_device(adev->platform,
814 snd_device,
815 &num_devices,
816 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530817 for (i = 0; i < num_devices; i++) {
818 enable_snd_device(adev, new_snd_devices[i]);
819 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800820 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700821 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530822
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530823
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530824 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
825 (audio_extn_a2dp_start_playback() < 0)) {
826 ALOGE(" fail to configure A2dp control path ");
827 return -EINVAL;
828 }
829
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700830 /* due to the possibility of calibration overwrite between listen
831 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700832 audio_extn_sound_trigger_update_device_status(snd_device,
833 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530834 audio_extn_listen_update_device_status(snd_device,
835 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700836 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700837 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700838 audio_extn_sound_trigger_update_device_status(snd_device,
839 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530840 audio_extn_listen_update_device_status(snd_device,
841 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700842 return -EINVAL;
843 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300844 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700845 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530846
847 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
848 !adev->native_playback_enabled &&
849 audio_is_true_native_stream_active(adev)) {
850 ALOGD("%s: %d: napb: enabling native mode in hardware",
851 __func__, __LINE__);
852 audio_route_apply_and_update_path(adev->audio_route,
853 "true-native-mode");
854 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530855 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857 return 0;
858}
859
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700860int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700861 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530863 int i, num_devices = 0;
864 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700865 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
866
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800867 if (snd_device < SND_DEVICE_MIN ||
868 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800869 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800870 return -EINVAL;
871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
873 ALOGE("%s: device ref cnt is already 0", __func__);
874 return -EINVAL;
875 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700876
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700878
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700879 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
880 ALOGE("%s: Invalid sound device returned", __func__);
881 return -EINVAL;
882 }
883
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700885 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530886
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800887 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
888 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700889 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700890 } else if (platform_split_snd_device(adev->platform,
891 snd_device,
892 &num_devices,
893 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530894 for (i = 0; i < num_devices; i++) {
895 disable_snd_device(adev, new_snd_devices[i]);
896 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300897 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700898 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300899 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700900
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530901 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
902 audio_extn_a2dp_stop_playback();
903
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700904 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530905 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530906 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
907 adev->native_playback_enabled) {
908 ALOGD("%s: %d: napb: disabling native mode in hardware",
909 __func__, __LINE__);
910 audio_route_reset_and_update_path(adev->audio_route,
911 "true-native-mode");
912 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530913 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
914 adev->asrc_mode_enabled) {
915 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530916 disable_asrc_mode(adev);
917 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530918 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530919
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200920 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700921 audio_extn_sound_trigger_update_device_status(snd_device,
922 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530923 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800924 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927 return 0;
928}
929
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700930/*
931 legend:
932 uc - existing usecase
933 new_uc - new usecase
934 d1, d11, d2 - SND_DEVICE enums
935 a1, a2 - corresponding ANDROID device enums
936 B1, B2 - backend strings
937
938case 1
939 uc->dev d1 (a1) B1
940 new_uc->dev d1 (a1), d2 (a2) B1, B2
941
942 resolution: disable and enable uc->dev on d1
943
944case 2
945 uc->dev d1 (a1) B1
946 new_uc->dev d11 (a1) B1
947
948 resolution: need to switch uc since d1 and d11 are related
949 (e.g. speaker and voice-speaker)
950 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
951
952case 3
953 uc->dev d1 (a1) B1
954 new_uc->dev d2 (a2) B2
955
956 resolution: no need to switch uc
957
958case 4
959 uc->dev d1 (a1) B1
960 new_uc->dev d2 (a2) B1
961
962 resolution: disable enable uc-dev on d2 since backends match
963 we cannot enable two streams on two different devices if they
964 share the same backend. e.g. if offload is on speaker device using
965 QUAD_MI2S backend and a low-latency stream is started on voice-handset
966 using the same backend, offload must also be switched to voice-handset.
967
968case 5
969 uc->dev d1 (a1) B1
970 new_uc->dev d1 (a1), d2 (a2) B1
971
972 resolution: disable enable uc-dev on d2 since backends match
973 we cannot enable two streams on two different devices if they
974 share the same backend.
975
976case 6
977 uc->dev d1 (a1) B1
978 new_uc->dev d2 (a1) B2
979
980 resolution: no need to switch
981
982case 7
983 uc->dev d1 (a1), d2 (a2) B1, B2
984 new_uc->dev d1 (a1) B1
985
986 resolution: no need to switch
987
988*/
989static snd_device_t derive_playback_snd_device(void * platform,
990 struct audio_usecase *uc,
991 struct audio_usecase *new_uc,
992 snd_device_t new_snd_device)
993{
994 audio_devices_t a1 = uc->stream.out->devices;
995 audio_devices_t a2 = new_uc->stream.out->devices;
996
997 snd_device_t d1 = uc->out_snd_device;
998 snd_device_t d2 = new_snd_device;
999
1000 // Treat as a special case when a1 and a2 are not disjoint
1001 if ((a1 != a2) && (a1 & a2)) {
1002 snd_device_t d3[2];
1003 int num_devices = 0;
1004 int ret = platform_split_snd_device(platform,
1005 popcount(a1) > 1 ? d1 : d2,
1006 &num_devices,
1007 d3);
1008 if (ret < 0) {
1009 if (ret != -ENOSYS) {
1010 ALOGW("%s failed to split snd_device %d",
1011 __func__,
1012 popcount(a1) > 1 ? d1 : d2);
1013 }
1014 goto end;
1015 }
1016
1017 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1018 // But if it does happen, we need to give priority to d2 if
1019 // the combo devices active on the existing usecase share a backend.
1020 // This is because we cannot have a usecase active on a combo device
1021 // and a new usecase requests one device in this combo pair.
1022 if (platform_check_backends_match(d3[0], d3[1])) {
1023 return d2; // case 5
1024 } else {
1025 return d1; // case 1
1026 }
1027 } else {
1028 if (platform_check_backends_match(d1, d2)) {
1029 return d2; // case 2, 4
1030 } else {
1031 return d1; // case 6, 3
1032 }
1033 }
1034
1035end:
1036 return d2; // return whatever was calculated before.
1037}
1038
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301040 struct audio_usecase *uc_info,
1041 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001042{
1043 struct listnode *node;
1044 struct audio_usecase *usecase;
1045 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301046 snd_device_t uc_derive_snd_device;
1047 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001048 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001049 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301050 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001051 /*
1052 * This function is to make sure that all the usecases that are active on
1053 * the hardware codec backend are always routed to any one device that is
1054 * handled by the hardware codec.
1055 * For example, if low-latency and deep-buffer usecases are currently active
1056 * on speaker and out_set_parameters(headset) is received on low-latency
1057 * output, then we have to make sure deep-buffer is also switched to headset,
1058 * because of the limitation that both the devices cannot be enabled
1059 * at the same time as they share the same backend.
1060 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001061 /*
1062 * This call is to check if we need to force routing for a particular stream
1063 * If there is a backend configuration change for the device when a
1064 * new stream starts, then ADM needs to be closed and re-opened with the new
1065 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001066 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001067 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001068 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1069 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301070 /* For a2dp device reconfigure all active sessions
1071 * with new AFE encoder format based on a2dp state
1072 */
1073 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1074 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1075 audio_extn_a2dp_is_force_device_switch()) {
1076 force_routing = true;
1077 force_restart_session = true;
1078 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301079 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1080
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001082 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001083 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1085 switch_device[i] = false;
1086
1087 list_for_each(node, &adev->usecase_list) {
1088 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001089
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301090 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1091 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301092 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301093 platform_get_snd_device_name(usecase->out_snd_device),
1094 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301095 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1096 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1097 usecase, uc_info, snd_device);
1098 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1099 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1100 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1101 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1102 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1103 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1104 ((force_restart_session) ||
1105 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301106 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1107 __func__, use_case_table[usecase->id],
1108 platform_get_snd_device_name(usecase->out_snd_device));
1109 disable_audio_route(adev, usecase);
1110 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301111 /* Enable existing usecase on derived playback device */
1112 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301113 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301114 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 }
1116 }
1117
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301118 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1119 num_uc_to_switch);
1120
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001122 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301124 /* Make sure the previous devices to be disabled first and then enable the
1125 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 list_for_each(node, &adev->usecase_list) {
1127 usecase = node_to_item(node, struct audio_usecase, list);
1128 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001129 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 }
1131 }
1132
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001133 list_for_each(node, &adev->usecase_list) {
1134 usecase = node_to_item(node, struct audio_usecase, list);
1135 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301136 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001137 }
1138 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 /* Re-route all the usecases on the shared backend other than the
1141 specified usecase to new snd devices */
1142 list_for_each(node, &adev->usecase_list) {
1143 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301144 /* Update the out_snd_device only before enabling the audio route */
1145 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301146 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301147 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301148 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301149 use_case_table[usecase->id],
1150 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001151 /* Update voc calibration before enabling VoIP route */
1152 if (usecase->type == VOIP_CALL)
1153 status = platform_switch_voice_call_device_post(adev->platform,
1154 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001155 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301156 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301157 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 }
1159 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001160 }
1161}
1162
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301163static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001164 struct audio_usecase *uc_info,
1165 snd_device_t snd_device)
1166{
1167 struct listnode *node;
1168 struct audio_usecase *usecase;
1169 bool switch_device[AUDIO_USECASE_MAX];
1170 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301171 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001172 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001173
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301174 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1175 snd_device);
1176 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301177
1178 /*
1179 * Make sure out devices is checked against out codec backend device and
1180 * also in devices against in codec backend. Checking out device against in
1181 * codec backend or vice versa causes issues.
1182 */
1183 if (uc_info->type == PCM_CAPTURE)
1184 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001185 /*
1186 * This function is to make sure that all the active capture usecases
1187 * are always routed to the same input sound device.
1188 * For example, if audio-record and voice-call usecases are currently
1189 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1190 * is received for voice call then we have to make sure that audio-record
1191 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1192 * because of the limitation that two devices cannot be enabled
1193 * at the same time if they share the same backend.
1194 */
1195 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1196 switch_device[i] = false;
1197
1198 list_for_each(node, &adev->usecase_list) {
1199 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301200 /*
1201 * TODO: Enhance below condition to handle BT sco/USB multi recording
1202 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001203 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001204 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301205 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301206 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301207 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301208 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001209 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1211 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001212 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001213 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214 switch_device[usecase->id] = true;
1215 num_uc_to_switch++;
1216 }
1217 }
1218
1219 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001220 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001221
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301222 /* Make sure the previous devices to be disabled first and then enable the
1223 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001224 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 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001228 }
1229 }
1230
1231 list_for_each(node, &adev->usecase_list) {
1232 usecase = node_to_item(node, struct audio_usecase, list);
1233 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001234 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001235 }
1236 }
1237
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001238 /* Re-route all the usecases on the shared backend other than the
1239 specified usecase to new snd devices */
1240 list_for_each(node, &adev->usecase_list) {
1241 usecase = node_to_item(node, struct audio_usecase, list);
1242 /* Update the in_snd_device only before enabling the audio route */
1243 if (switch_device[usecase->id] ) {
1244 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001245 if (usecase->type != VOICE_CALL) {
1246 /* Update voc calibration before enabling VoIP route */
1247 if (usecase->type == VOIP_CALL)
1248 status = platform_switch_voice_call_device_post(adev->platform,
1249 usecase->out_snd_device,
1250 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301251 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001252 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001253 }
1254 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001255 }
1256}
1257
Mingming Yin3a941d42016-02-17 18:08:05 -08001258static void reset_hdmi_sink_caps(struct stream_out *out) {
1259 int i = 0;
1260
1261 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1262 out->supported_channel_masks[i] = 0;
1263 }
1264 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1265 out->supported_formats[i] = 0;
1266 }
1267 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1268 out->supported_sample_rates[i] = 0;
1269 }
1270}
1271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001273static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274{
Mingming Yin3a941d42016-02-17 18:08:05 -08001275 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001276 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277
Mingming Yin3a941d42016-02-17 18:08:05 -08001278 reset_hdmi_sink_caps(out);
1279
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001280 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001281 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001282 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001283 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001284 }
1285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001286 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001288 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001289 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001290 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1291 case 6:
1292 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1293 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1294 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1295 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1296 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1297 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 break;
1299 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001300 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001301 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 break;
1303 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001304
1305 // check channel format caps
1306 i = 0;
1307 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1308 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1309 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1310 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1311 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1312 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1313 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1314 }
1315
1316 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1317 ALOGV(":%s HDMI supports DTS format", __func__);
1318 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1319 }
1320
1321 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1322 ALOGV(":%s HDMI supports DTS HD format", __func__);
1323 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1324 }
1325
1326
1327 // check sample rate caps
1328 i = 0;
1329 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1330 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1331 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1332 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1333 }
1334 }
1335
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001336 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337}
1338
Alexy Josephb1379942016-01-29 15:49:38 -08001339audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001340 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001341{
1342 struct audio_usecase *usecase;
1343 struct listnode *node;
1344
1345 list_for_each(node, &adev->usecase_list) {
1346 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001347 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001348 ALOGV("%s: usecase id %d", __func__, usecase->id);
1349 return usecase->id;
1350 }
1351 }
1352 return USECASE_INVALID;
1353}
1354
Alexy Josephb1379942016-01-29 15:49:38 -08001355struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001356 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001357{
1358 struct audio_usecase *usecase;
1359 struct listnode *node;
1360
1361 list_for_each(node, &adev->usecase_list) {
1362 usecase = node_to_item(node, struct audio_usecase, list);
1363 if (usecase->id == uc_id)
1364 return usecase;
1365 }
1366 return NULL;
1367}
1368
Dhananjay Kumard4833242016-10-06 22:09:12 +05301369struct stream_in *get_next_active_input(const struct audio_device *adev)
1370{
1371 struct audio_usecase *usecase;
1372 struct listnode *node;
1373
1374 list_for_each_reverse(node, &adev->usecase_list) {
1375 usecase = node_to_item(node, struct audio_usecase, list);
1376 if (usecase->type == PCM_CAPTURE)
1377 return usecase->stream.in;
1378 }
1379 return NULL;
1380}
1381
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301382/*
1383 * is a true native playback active
1384 */
1385bool audio_is_true_native_stream_active(struct audio_device *adev)
1386{
1387 bool active = false;
1388 int i = 0;
1389 struct listnode *node;
1390
1391 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1392 ALOGV("%s:napb: not in true mode or non hdphones device",
1393 __func__);
1394 active = false;
1395 goto exit;
1396 }
1397
1398 list_for_each(node, &adev->usecase_list) {
1399 struct audio_usecase *uc;
1400 uc = node_to_item(node, struct audio_usecase, list);
1401 struct stream_out *curr_out =
1402 (struct stream_out*) uc->stream.out;
1403
1404 if (curr_out && PCM_PLAYBACK == uc->type) {
1405 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1406 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1407 uc->id, curr_out->sample_rate,
1408 curr_out->bit_width,
1409 platform_get_snd_device_name(uc->out_snd_device));
1410
1411 if (is_offload_usecase(uc->id) &&
1412 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1413 active = true;
1414 ALOGD("%s:napb:native stream detected", __func__);
1415 }
1416 }
1417 }
1418exit:
1419 return active;
1420}
1421
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301422/*
1423 * if native DSD playback active
1424 */
1425bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1426{
1427 bool active = false;
1428 struct listnode *node = NULL;
1429 struct audio_usecase *uc = NULL;
1430 struct stream_out *curr_out = NULL;
1431
1432 list_for_each(node, &adev->usecase_list) {
1433 uc = node_to_item(node, struct audio_usecase, list);
1434 curr_out = (struct stream_out*) uc->stream.out;
1435
1436 if (curr_out && PCM_PLAYBACK == uc->type &&
1437 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1438 active = true;
1439 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301440 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301441 }
1442 }
1443 return active;
1444}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301445
1446static bool force_device_switch(struct audio_usecase *usecase)
1447{
1448 bool ret = false;
1449 bool is_it_true_mode = false;
1450
1451 if (is_offload_usecase(usecase->id) &&
1452 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001453 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1454 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1455 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301456 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1457 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1458 (!is_it_true_mode && adev->native_playback_enabled)){
1459 ret = true;
1460 ALOGD("napb: time to toggle native mode");
1461 }
1462 }
1463
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301464 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301465 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1466 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301467 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001468 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301469 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301470 ALOGD("Force a2dp device switch to update new encoder config");
1471 ret = true;
1472 }
1473
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301474 return ret;
1475}
1476
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001477int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001479 snd_device_t out_snd_device = SND_DEVICE_NONE;
1480 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481 struct audio_usecase *usecase = NULL;
1482 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001483 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001484 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001485 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301488 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1489
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001490 usecase = get_usecase_from_list(adev, uc_id);
1491 if (usecase == NULL) {
1492 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1493 return -EINVAL;
1494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001496 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001497 (usecase->type == VOIP_CALL) ||
1498 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301499 if(usecase->stream.out == NULL) {
1500 ALOGE("%s: stream.out is NULL", __func__);
1501 return -EINVAL;
1502 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001503 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001504 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001505 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 usecase->devices = usecase->stream.out->devices;
1507 } else {
1508 /*
1509 * If the voice call is active, use the sound devices of voice call usecase
1510 * so that it would not result any device switch. All the usecases will
1511 * be switched to new device when select_devices() is called for voice call
1512 * usecase. This is to avoid switching devices for voice call when
1513 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001514 * choose voice call device only if the use case device is
1515 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001516 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001517 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001518 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001519 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001520 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1521 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301522 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1523 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001524 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 in_snd_device = vc_usecase->in_snd_device;
1526 out_snd_device = vc_usecase->out_snd_device;
1527 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001528 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001529 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001530 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh02ef86f2017-04-21 15:36:04 +08001531 if (usecase->stream.out != NULL) {
1532 out_snd_device_backend_match = platform_check_backends_match(
1533 voip_usecase->out_snd_device,
1534 platform_get_output_snd_device(
1535 adev->platform,
1536 usecase->stream.out));
1537 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001538 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001539 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1540 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001541 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001542 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001543 in_snd_device = voip_usecase->in_snd_device;
1544 out_snd_device = voip_usecase->out_snd_device;
1545 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001546 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001547 hfp_ucid = audio_extn_hfp_get_usecase();
1548 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001549 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001550 in_snd_device = hfp_usecase->in_snd_device;
1551 out_snd_device = hfp_usecase->out_snd_device;
1552 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 }
1554 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301555 if (usecase->stream.out == NULL) {
1556 ALOGE("%s: stream.out is NULL", __func__);
1557 return -EINVAL;
1558 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 usecase->devices = usecase->stream.out->devices;
1560 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001561 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001562 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001563 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001564 if (usecase->stream.out == adev->primary_output &&
1565 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001566 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001567 select_devices(adev, adev->active_input->usecase);
1568 }
1569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301571 if (usecase->stream.in == NULL) {
1572 ALOGE("%s: stream.in is NULL", __func__);
1573 return -EINVAL;
1574 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575 usecase->devices = usecase->stream.in->device;
1576 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001577 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001578 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001579 if (adev->active_input &&
1580 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301581 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1582 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1583 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001584 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001585 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001586 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1587 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001588 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001589 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001590 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001591 }
1592 }
1593
1594 if (out_snd_device == usecase->out_snd_device &&
1595 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301596
1597 if (!force_device_switch(usecase))
1598 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599 }
1600
sangwoobc677242013-08-08 16:53:43 +09001601 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001602 out_snd_device, platform_get_snd_device_name(out_snd_device),
1603 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001605 /*
1606 * Limitation: While in call, to do a device switch we need to disable
1607 * and enable both RX and TX devices though one of them is same as current
1608 * device.
1609 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001610 if ((usecase->type == VOICE_CALL) &&
1611 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1612 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001613 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001614 }
1615
1616 if (((usecase->type == VOICE_CALL) ||
1617 (usecase->type == VOIP_CALL)) &&
1618 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1619 /* Disable sidetone only if voice/voip call already exists */
1620 if (voice_is_call_state_active(adev) ||
1621 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001622 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001623
1624 /* Disable aanc only if voice call exists */
1625 if (voice_is_call_state_active(adev))
1626 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001627 }
1628
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001629 /* Disable current sound devices */
1630 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001631 disable_audio_route(adev, usecase);
1632 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633 }
1634
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001635 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001636 disable_audio_route(adev, usecase);
1637 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638 }
1639
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001640 /* Applicable only on the targets that has external modem.
1641 * New device information should be sent to modem before enabling
1642 * the devices to reduce in-call device switch time.
1643 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001644 if ((usecase->type == VOICE_CALL) &&
1645 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1646 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001647 status = platform_switch_voice_call_enable_device_config(adev->platform,
1648 out_snd_device,
1649 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001650 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001651
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 /* Enable new sound devices */
1653 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001654 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301655 if (platform_check_codec_asrc_support(adev->platform))
1656 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001657 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658 }
1659
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001660 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301661 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001662 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664
Avinash Vaish71a8b972014-07-24 15:36:33 +05301665 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001666 status = platform_switch_voice_call_device_post(adev->platform,
1667 out_snd_device,
1668 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301669 enable_audio_route_for_voice_usecases(adev, usecase);
1670 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001671
sangwoo170731f2013-06-08 15:36:36 +09001672 usecase->in_snd_device = in_snd_device;
1673 usecase->out_snd_device = out_snd_device;
1674
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301675 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1676 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301677 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001678 if ((24 == usecase->stream.out->bit_width) &&
1679 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1680 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1681 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1682 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1683 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1684 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1685 /*
1686 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1687 * configured device sample rate, if not update the COPP rate to be equal to the
1688 * device sample rate, else open COPP at stream sample rate
1689 */
1690 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1691 usecase->stream.out->sample_rate,
1692 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301693 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1694 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001695 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1696 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1697 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1698 }
1699
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001700 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001701 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001702 audio_extn_gef_notify_device_config(
1703 usecase->stream.out->devices,
1704 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001705 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001706 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001707 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301708 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001709 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001710
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001711 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001712 /* Enable aanc only if voice call exists */
1713 if (voice_is_call_state_active(adev))
1714 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1715
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001716 /* Enable sidetone only if other voice/voip call already exists */
1717 if (voice_is_call_state_active(adev) ||
1718 voice_extn_compress_voip_is_started(adev))
1719 voice_set_sidetone(adev, out_snd_device, true);
1720 }
1721
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001722 /* Applicable only on the targets that has external modem.
1723 * Enable device command should be sent to modem only after
1724 * enabling voice call mixer controls
1725 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001726 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001727 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1728 out_snd_device,
1729 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301730 ALOGD("%s: done",__func__);
1731
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 return status;
1733}
1734
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735static int stop_input_stream(struct stream_in *in)
1736{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301737 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738 struct audio_usecase *uc_info;
1739 struct audio_device *adev = in->dev;
1740
Eric Laurent994a6932013-07-17 11:51:42 -07001741 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001742 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 uc_info = get_usecase_from_list(adev, in->usecase);
1744 if (uc_info == NULL) {
1745 ALOGE("%s: Could not find the usecase (%d) in the list",
1746 __func__, in->usecase);
1747 return -EINVAL;
1748 }
1749
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001750 /* Close in-call recording streams */
1751 voice_check_and_stop_incall_rec_usecase(adev, in);
1752
Eric Laurent150dbfe2013-02-27 14:31:02 -08001753 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001754 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755
1756 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001757 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001759 list_remove(&uc_info->list);
1760 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001762 adev->active_input = get_next_active_input(adev);
1763
Eric Laurent994a6932013-07-17 11:51:42 -07001764 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 return ret;
1766}
1767
1768int start_input_stream(struct stream_in *in)
1769{
1770 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001771 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772 struct audio_usecase *uc_info;
1773 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301774 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775
Mingming Yin2664a5b2015-09-03 10:53:11 -07001776 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1777 if (get_usecase_from_list(adev, usecase) == NULL)
1778 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301779 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1780 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001781
Naresh Tanniru80659832014-06-04 18:17:56 +05301782
1783 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301784 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301785 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301786 goto error_config;
1787 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301788
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001789 /* Check if source matches incall recording usecase criteria */
1790 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1791 if (ret)
1792 goto error_config;
1793 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001794 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1795
1796 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1797 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1798 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001799 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001800 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001801
Eric Laurentb23d5282013-05-14 15:27:20 -07001802 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 if (in->pcm_device_id < 0) {
1804 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1805 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001806 ret = -EINVAL;
1807 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001808 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001809
1810 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001812
1813 if (!uc_info) {
1814 ret = -ENOMEM;
1815 goto error_config;
1816 }
1817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 uc_info->id = in->usecase;
1819 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001820 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001821 uc_info->devices = in->device;
1822 uc_info->in_snd_device = SND_DEVICE_NONE;
1823 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001825 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301826 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1827 adev->perf_lock_opts,
1828 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301831 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1832 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001833
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301834 if (audio_extn_cin_attached_usecase(in->usecase)) {
1835 ret = audio_extn_cin_start_input_stream(in);
1836 if (ret)
1837 goto error_open;
1838 else
1839 goto done_open;
1840 }
1841
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001842 unsigned int flags = PCM_IN;
1843 unsigned int pcm_open_retry_count = 0;
1844
1845 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1846 flags |= PCM_MMAP | PCM_NOIRQ;
1847 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001848 } else if (in->realtime) {
1849 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001850 }
1851
1852 while (1) {
1853 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1854 flags, &in->config);
1855 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1856 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1857 if (in->pcm != NULL) {
1858 pcm_close(in->pcm);
1859 in->pcm = NULL;
1860 }
1861 if (pcm_open_retry_count-- == 0) {
1862 ret = -EIO;
1863 goto error_open;
1864 }
1865 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1866 continue;
1867 }
1868 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001870
1871 ALOGV("%s: pcm_prepare", __func__);
1872 ret = pcm_prepare(in->pcm);
1873 if (ret < 0) {
1874 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1875 pcm_close(in->pcm);
1876 in->pcm = NULL;
1877 goto error_open;
1878 }
1879
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001880 register_in_stream(in);
1881 if (in->realtime) {
1882 ret = pcm_start(in->pcm);
1883 if (ret < 0)
1884 goto error_open;
1885 }
1886
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301887done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301888 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001889 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001890
Eric Laurentc8400632013-02-14 19:04:54 -08001891 return ret;
1892
1893error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301894 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001896error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301897 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301898 /*
1899 * sleep 50ms to allow sufficient time for kernel
1900 * drivers to recover incases like SSR.
1901 */
1902 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001903 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001904
1905 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906}
1907
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001908void lock_input_stream(struct stream_in *in)
1909{
1910 pthread_mutex_lock(&in->pre_lock);
1911 pthread_mutex_lock(&in->lock);
1912 pthread_mutex_unlock(&in->pre_lock);
1913}
1914
1915void lock_output_stream(struct stream_out *out)
1916{
1917 pthread_mutex_lock(&out->pre_lock);
1918 pthread_mutex_lock(&out->lock);
1919 pthread_mutex_unlock(&out->pre_lock);
1920}
1921
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001922/* must be called with out->lock locked */
1923static int send_offload_cmd_l(struct stream_out* out, int command)
1924{
1925 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1926
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001927 if (!cmd) {
1928 ALOGE("failed to allocate mem for command 0x%x", command);
1929 return -ENOMEM;
1930 }
1931
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001932 ALOGVV("%s %d", __func__, command);
1933
1934 cmd->cmd = command;
1935 list_add_tail(&out->offload_cmd_list, &cmd->node);
1936 pthread_cond_signal(&out->offload_cond);
1937 return 0;
1938}
1939
1940/* must be called iwth out->lock locked */
1941static void stop_compressed_output_l(struct stream_out *out)
1942{
1943 out->offload_state = OFFLOAD_STATE_IDLE;
1944 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001945 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 if (out->compr != NULL) {
1947 compress_stop(out->compr);
1948 while (out->offload_thread_blocked) {
1949 pthread_cond_wait(&out->cond, &out->lock);
1950 }
1951 }
1952}
1953
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001954bool is_offload_usecase(audio_usecase_t uc_id)
1955{
1956 unsigned int i;
1957 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1958 if (uc_id == offload_usecases[i])
1959 return true;
1960 }
1961 return false;
1962}
1963
Dhananjay Kumarac341582017-02-23 23:42:25 +05301964static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001965{
vivek mehta446c3962015-09-14 10:57:35 -07001966 audio_usecase_t ret_uc = USECASE_INVALID;
1967 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001968 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001969 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301970 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001971 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1972 else
1973 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001974
vivek mehta446c3962015-09-14 10:57:35 -07001975 pthread_mutex_lock(&adev->lock);
1976 if (get_usecase_from_list(adev, ret_uc) != NULL)
1977 ret_uc = USECASE_INVALID;
1978 pthread_mutex_unlock(&adev->lock);
1979
1980 return ret_uc;
1981 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001982
1983 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001984 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1985 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1986 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1987 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001988 break;
1989 }
1990 }
vivek mehta446c3962015-09-14 10:57:35 -07001991
1992 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1993 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001994}
1995
1996static void free_offload_usecase(struct audio_device *adev,
1997 audio_usecase_t uc_id)
1998{
vivek mehta446c3962015-09-14 10:57:35 -07001999 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002000 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002001
2002 if (!adev->multi_offload_enable)
2003 return;
2004
2005 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2006 if (offload_usecases[offload_uc_index] == uc_id) {
2007 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002008 break;
2009 }
2010 }
2011 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2012}
2013
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002014static void *offload_thread_loop(void *context)
2015{
2016 struct stream_out *out = (struct stream_out *) context;
2017 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002018 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2021 set_sched_policy(0, SP_FOREGROUND);
2022 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2023
2024 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002025 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026 for (;;) {
2027 struct offload_cmd *cmd = NULL;
2028 stream_callback_event_t event;
2029 bool send_callback = false;
2030
2031 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2032 __func__, list_empty(&out->offload_cmd_list),
2033 out->offload_state);
2034 if (list_empty(&out->offload_cmd_list)) {
2035 ALOGV("%s SLEEPING", __func__);
2036 pthread_cond_wait(&out->offload_cond, &out->lock);
2037 ALOGV("%s RUNNING", __func__);
2038 continue;
2039 }
2040
2041 item = list_head(&out->offload_cmd_list);
2042 cmd = node_to_item(item, struct offload_cmd, node);
2043 list_remove(item);
2044
2045 ALOGVV("%s STATE %d CMD %d out->compr %p",
2046 __func__, out->offload_state, cmd->cmd, out->compr);
2047
2048 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2049 free(cmd);
2050 break;
2051 }
2052
2053 if (out->compr == NULL) {
2054 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002055 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002056 pthread_cond_signal(&out->cond);
2057 continue;
2058 }
2059 out->offload_thread_blocked = true;
2060 pthread_mutex_unlock(&out->lock);
2061 send_callback = false;
2062 switch(cmd->cmd) {
2063 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002064 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002066 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002067 send_callback = true;
2068 event = STREAM_CBK_EVENT_WRITE_READY;
2069 break;
2070 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002071 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302072 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002073 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302074 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002075 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302076 if (ret < 0)
2077 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302078 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302079 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002080 compress_drain(out->compr);
2081 else
2082 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302083 if (ret != -ENETRESET) {
2084 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302085 pthread_mutex_lock(&out->lock);
2086 out->send_new_metadata = 1;
2087 out->send_next_track_params = true;
2088 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302089 event = STREAM_CBK_EVENT_DRAIN_READY;
2090 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2091 } else
2092 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 break;
2094 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002095 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002097 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 send_callback = true;
2099 event = STREAM_CBK_EVENT_DRAIN_READY;
2100 break;
2101 default:
2102 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2103 break;
2104 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002105 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106 out->offload_thread_blocked = false;
2107 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002108 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002109 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002111 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 free(cmd);
2113 }
2114
2115 pthread_cond_signal(&out->cond);
2116 while (!list_empty(&out->offload_cmd_list)) {
2117 item = list_head(&out->offload_cmd_list);
2118 list_remove(item);
2119 free(node_to_item(item, struct offload_cmd, node));
2120 }
2121 pthread_mutex_unlock(&out->lock);
2122
2123 return NULL;
2124}
2125
2126static int create_offload_callback_thread(struct stream_out *out)
2127{
2128 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2129 list_init(&out->offload_cmd_list);
2130 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2131 offload_thread_loop, out);
2132 return 0;
2133}
2134
2135static int destroy_offload_callback_thread(struct stream_out *out)
2136{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002137 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002138 stop_compressed_output_l(out);
2139 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2140
2141 pthread_mutex_unlock(&out->lock);
2142 pthread_join(out->offload_thread, (void **) NULL);
2143 pthread_cond_destroy(&out->offload_cond);
2144
2145 return 0;
2146}
2147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002148static int stop_output_stream(struct stream_out *out)
2149{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302150 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 struct audio_usecase *uc_info;
2152 struct audio_device *adev = out->dev;
2153
Eric Laurent994a6932013-07-17 11:51:42 -07002154 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002155 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 uc_info = get_usecase_from_list(adev, out->usecase);
2157 if (uc_info == NULL) {
2158 ALOGE("%s: Could not find the usecase (%d) in the list",
2159 __func__, out->usecase);
2160 return -EINVAL;
2161 }
2162
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002163 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302164 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002165 if (adev->visualizer_stop_output != NULL)
2166 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002167
2168 audio_extn_dts_remove_state_notifier_node(out->usecase);
2169
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002170 if (adev->offload_effects_stop_output != NULL)
2171 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2172 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002173
Eric Laurent150dbfe2013-02-27 14:31:02 -08002174 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002175 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002176
2177 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002178 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002180 list_remove(&uc_info->list);
2181 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002183 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302184 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002185 ALOGV("Disable passthrough , reset mixer to pcm");
2186 /* NO_PASSTHROUGH */
2187 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002188 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002189 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2190 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002191
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302192 /* Must be called after removing the usecase from list */
2193 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302194 audio_extn_keep_alive_start();
2195
Manish Dewangan14956cc2017-02-14 18:54:42 +05302196 /*reset delay_param to 0*/
2197 out->delay_param.start_delay = 0;
2198
Eric Laurent994a6932013-07-17 11:51:42 -07002199 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 return ret;
2201}
2202
2203int start_output_stream(struct stream_out *out)
2204{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206 struct audio_usecase *uc_info;
2207 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302208 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002209 char mixer_ctl_name[128];
2210 struct mixer_ctl *ctl = NULL;
2211 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002213 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2214 ret = -EINVAL;
2215 goto error_config;
2216 }
2217
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302218 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2219 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2220 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302221
Naresh Tanniru80659832014-06-04 18:17:56 +05302222 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302223 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302224 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302225 goto error_config;
2226 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302227
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302228 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2229 if (!audio_extn_a2dp_is_ready()) {
2230 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2231 //combo usecase just by pass a2dp
2232 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2233 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2234 } else {
2235 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2236 ret = -EAGAIN;
2237 goto error_config;
2238 }
2239 }
2240 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002241 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 if (out->pcm_device_id < 0) {
2243 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2244 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002245 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002246 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 }
2248
2249 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002250
2251 if (!uc_info) {
2252 ret = -ENOMEM;
2253 goto error_config;
2254 }
2255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 uc_info->id = out->usecase;
2257 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002258 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259 uc_info->devices = out->devices;
2260 uc_info->in_snd_device = SND_DEVICE_NONE;
2261 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002262 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302264 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2265 adev->perf_lock_opts,
2266 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302267
2268 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2269 audio_extn_keep_alive_stop();
2270 if (audio_extn_passthru_is_enabled() &&
2271 audio_extn_passthru_is_passthrough_stream(out)) {
2272 audio_extn_passthru_on_start(out);
2273 audio_extn_passthru_update_stream_configuration(adev, out);
2274 }
2275 }
2276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 select_devices(adev, out->usecase);
2278
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002279 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2280 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002281 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002282 unsigned int flags = PCM_OUT;
2283 unsigned int pcm_open_retry_count = 0;
2284 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2285 flags |= PCM_MMAP | PCM_NOIRQ;
2286 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002287 } else if (out->realtime) {
2288 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002289 } else
2290 flags |= PCM_MONOTONIC;
2291
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002292 if ((adev->vr_audio_mode_enabled) &&
2293 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2294 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2295 "PCM_Dev %d Topology", out->pcm_device_id);
2296 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2297 if (!ctl) {
2298 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2299 __func__, mixer_ctl_name);
2300 } else {
2301 //if success use ULLPP
2302 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2303 __func__, mixer_ctl_name, out->pcm_device_id);
2304 //There is a still a possibility that some sessions
2305 // that request for FAST|RAW when 3D audio is active
2306 //can go through ULLPP. Ideally we expects apps to
2307 //listen to audio focus and stop concurrent playback
2308 //Also, we will look for mode flag (voice_in_communication)
2309 //before enabling the realtime flag.
2310 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2311 }
2312 }
2313
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002314 while (1) {
2315 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2316 flags, &out->config);
2317 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2318 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2319 if (out->pcm != NULL) {
2320 pcm_close(out->pcm);
2321 out->pcm = NULL;
2322 }
2323 if (pcm_open_retry_count-- == 0) {
2324 ret = -EIO;
2325 goto error_open;
2326 }
2327 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2328 continue;
2329 }
2330 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002331 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002332
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002333 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2334 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002335
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002336 ALOGV("%s: pcm_prepare", __func__);
2337 if (pcm_is_ready(out->pcm)) {
2338 ret = pcm_prepare(out->pcm);
2339 if (ret < 0) {
2340 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2341 pcm_close(out->pcm);
2342 out->pcm = NULL;
2343 goto error_open;
2344 }
2345 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302346 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2347 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002348 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002349 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2350 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002352 out->compr = compress_open(adev->snd_card,
2353 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 COMPRESS_IN, &out->compr_config);
2355 if (out->compr && !is_compress_ready(out->compr)) {
2356 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2357 compress_close(out->compr);
2358 out->compr = NULL;
2359 ret = -EIO;
2360 goto error_open;
2361 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302362 /* compress_open sends params of the track, so reset the flag here */
2363 out->is_compr_metadata_avail = false;
2364
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002365 if (out->offload_callback)
2366 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002367
Fred Oh3f43e742015-03-04 18:42:34 -08002368 /* Since small bufs uses blocking writes, a write will be blocked
2369 for the default max poll time (20s) in the event of an SSR.
2370 Reduce the poll time to observe and deal with SSR faster.
2371 */
Ashish Jain5106d362016-05-11 19:23:33 +05302372 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002373 compress_set_max_poll_wait(out->compr, 1000);
2374 }
2375
Manish Dewangan69426c82017-01-30 17:35:36 +05302376 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302377 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan27346042017-03-01 12:56:12 +05302378 /* set render window if it was set before compress_open() */
2379 if (out->render_window.render_ws != 0 && out->render_window.render_we != 0)
2380 audio_extn_utils_compress_set_render_window(out,
2381 &out->render_window);
Manish Dewangan14956cc2017-02-14 18:54:42 +05302382 audio_extn_utils_compress_set_start_delay(out, &out->delay_param);
Manish Dewangan69426c82017-01-30 17:35:36 +05302383
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002384 audio_extn_dts_create_state_notifier_node(out->usecase);
2385 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2386 popcount(out->channel_mask),
2387 out->playback_started);
2388
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002389#ifdef DS1_DOLBY_DDP_ENABLED
2390 if (audio_extn_is_dolby_format(out->format))
2391 audio_extn_dolby_send_ddp_endp_params(adev);
2392#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302393 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2394 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002395 if (adev->visualizer_start_output != NULL)
2396 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2397 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302398 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002399 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002400 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002402
2403 if (ret == 0) {
2404 register_out_stream(out);
2405 if (out->realtime) {
2406 ret = pcm_start(out->pcm);
2407 if (ret < 0)
2408 goto error_open;
2409 }
2410 }
2411
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302412 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002413 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002414
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002415 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002416error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302417 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002419error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302420 /*
2421 * sleep 50ms to allow sufficient time for kernel
2422 * drivers to recover incases like SSR.
2423 */
2424 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002425 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426}
2427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428static int check_input_parameters(uint32_t sample_rate,
2429 audio_format_t format,
2430 int channel_count)
2431{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002432 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302434 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2435 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2436 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002437 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302438 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002439
2440 switch (channel_count) {
2441 case 1:
2442 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302443 case 3:
2444 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002445 case 6:
2446 break;
2447 default:
2448 ret = -EINVAL;
2449 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450
2451 switch (sample_rate) {
2452 case 8000:
2453 case 11025:
2454 case 12000:
2455 case 16000:
2456 case 22050:
2457 case 24000:
2458 case 32000:
2459 case 44100:
2460 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302461 case 96000:
2462 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463 break;
2464 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002465 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 }
2467
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002468 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469}
2470
2471static size_t get_input_buffer_size(uint32_t sample_rate,
2472 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002473 int channel_count,
2474 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475{
2476 size_t size = 0;
2477
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002478 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2479 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002481 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002482 if (is_low_latency)
2483 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302484
2485 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002487 /* make sure the size is multiple of 32 bytes
2488 * At 48 kHz mono 16-bit PCM:
2489 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2490 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2491 */
2492 size += 0x1f;
2493 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002494
2495 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496}
2497
Ashish Jain058165c2016-09-28 23:18:48 +05302498static size_t get_output_period_size(uint32_t sample_rate,
2499 audio_format_t format,
2500 int channel_count,
2501 int duration /*in millisecs*/)
2502{
2503 size_t size = 0;
2504 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2505
2506 if ((duration == 0) || (sample_rate == 0) ||
2507 (bytes_per_sample == 0) || (channel_count == 0)) {
2508 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2509 bytes_per_sample, channel_count);
2510 return -EINVAL;
2511 }
2512
2513 size = (sample_rate *
2514 duration *
2515 bytes_per_sample *
2516 channel_count) / 1000;
2517 /*
2518 * To have same PCM samples for all channels, the buffer size requires to
2519 * be multiple of (number of channels * bytes per sample)
2520 * For writes to succeed, the buffer must be written at address which is multiple of 32
2521 */
2522 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2523
2524 return (size/(channel_count * bytes_per_sample));
2525}
2526
Ashish Jain5106d362016-05-11 19:23:33 +05302527static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2528{
2529 uint64_t actual_frames_rendered = 0;
2530 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2531
2532 /* This adjustment accounts for buffering after app processor.
2533 * It is based on estimated DSP latency per use case, rather than exact.
2534 */
2535 int64_t platform_latency = platform_render_latency(out->usecase) *
2536 out->sample_rate / 1000000LL;
2537
2538 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2539 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2540 * hence only estimate.
2541 */
2542 int64_t signed_frames = out->written - kernel_buffer_size;
2543
2544 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2545
2546 if (signed_frames > 0)
2547 actual_frames_rendered = signed_frames;
2548
2549 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2550 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2551 (long long int)out->written, (int)kernel_buffer_size,
2552 audio_bytes_per_sample(out->compr_config.codec->format),
2553 popcount(out->channel_mask));
2554
2555 return actual_frames_rendered;
2556}
2557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2559{
2560 struct stream_out *out = (struct stream_out *)stream;
2561
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002562 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563}
2564
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002565static int out_set_sample_rate(struct audio_stream *stream __unused,
2566 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567{
2568 return -ENOSYS;
2569}
2570
2571static size_t out_get_buffer_size(const struct audio_stream *stream)
2572{
2573 struct stream_out *out = (struct stream_out *)stream;
2574
Dhananjay Kumarac341582017-02-23 23:42:25 +05302575 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002577 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2578 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302579 else if (is_offload_usecase(out->usecase) &&
2580 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302581 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002583 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002584 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585}
2586
2587static uint32_t out_get_channels(const struct audio_stream *stream)
2588{
2589 struct stream_out *out = (struct stream_out *)stream;
2590
2591 return out->channel_mask;
2592}
2593
2594static audio_format_t out_get_format(const struct audio_stream *stream)
2595{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 struct stream_out *out = (struct stream_out *)stream;
2597
2598 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599}
2600
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002601static int out_set_format(struct audio_stream *stream __unused,
2602 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603{
2604 return -ENOSYS;
2605}
2606
2607static int out_standby(struct audio_stream *stream)
2608{
2609 struct stream_out *out = (struct stream_out *)stream;
2610 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002611
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302612 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2613 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002615 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002617 if (adev->adm_deregister_stream)
2618 adev->adm_deregister_stream(adev->adm_data, out->handle);
2619
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002620 if (is_offload_usecase(out->usecase))
2621 stop_compressed_output_l(out);
2622
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002623 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002625 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2626 voice_extn_compress_voip_close_output_stream(stream);
2627 pthread_mutex_unlock(&adev->lock);
2628 pthread_mutex_unlock(&out->lock);
2629 ALOGD("VOIP output entered standby");
2630 return 0;
2631 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002632 if (out->pcm) {
2633 pcm_close(out->pcm);
2634 out->pcm = NULL;
2635 }
2636 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002637 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302638 out->send_next_track_params = false;
2639 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002640 out->gapless_mdata.encoder_delay = 0;
2641 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002642 if (out->compr != NULL) {
2643 compress_close(out->compr);
2644 out->compr = NULL;
2645 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002648 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 }
2650 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302651 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 return 0;
2653}
2654
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002655static int out_dump(const struct audio_stream *stream __unused,
2656 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657{
2658 return 0;
2659}
2660
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002661static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2662{
2663 int ret = 0;
2664 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002665
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002666 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002667 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002668 return -EINVAL;
2669 }
2670
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302671 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002672
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002673 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2674 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302675 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002676 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002677 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2678 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302679 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002680 }
2681
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002682 ALOGV("%s new encoder delay %u and padding %u", __func__,
2683 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2684
2685 return 0;
2686}
2687
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002688static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2689{
2690 return out == adev->primary_output || out == adev->voice_tx_output;
2691}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2694{
2695 struct stream_out *out = (struct stream_out *)stream;
2696 struct audio_device *adev = out->dev;
2697 struct str_parms *parms;
2698 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002699 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700
sangwoobc677242013-08-08 16:53:43 +09002701 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002702 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302704 if (!parms)
2705 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002706 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2707 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002709 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002710 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002712 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002713 * When HDMI cable is unplugged the music playback is paused and
2714 * the policy manager sends routing=0. But the audioflinger continues
2715 * to write data until standby time (3sec). As the HDMI core is
2716 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002717 * Avoid this by routing audio to speaker until standby.
2718 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002719 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2720 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302721 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002722 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2723 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002724 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302725 /*
2726 * When A2DP is disconnected the
2727 * music playback is paused and the policy manager sends routing=0
2728 * But the audioflingercontinues to write data until standby time
2729 * (3sec). As BT is turned off, the write gets blocked.
2730 * Avoid this by routing audio to speaker until standby.
2731 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002732 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302733 (val == AUDIO_DEVICE_NONE)) {
2734 val = AUDIO_DEVICE_OUT_SPEAKER;
2735 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302736 /* To avoid a2dp to sco overlapping / BT device improper state
2737 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302738 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302739 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2740 if (!audio_extn_a2dp_is_ready()) {
2741 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2742 //combo usecase just by pass a2dp
2743 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2744 val = AUDIO_DEVICE_OUT_SPEAKER;
2745 } else {
2746 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2747 /* update device to a2dp and don't route as BT returned error
2748 * However it is still possible a2dp routing called because
2749 * of current active device disconnection (like wired headset)
2750 */
2751 out->devices = val;
2752 pthread_mutex_unlock(&out->lock);
2753 pthread_mutex_unlock(&adev->lock);
2754 goto error;
2755 }
2756 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302757 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002758 /*
2759 * select_devices() call below switches all the usecases on the same
2760 * backend to the new device. Refer to check_usecases_codec_backend() in
2761 * the select_devices(). But how do we undo this?
2762 *
2763 * For example, music playback is active on headset (deep-buffer usecase)
2764 * and if we go to ringtones and select a ringtone, low-latency usecase
2765 * will be started on headset+speaker. As we can't enable headset+speaker
2766 * and headset devices at the same time, select_devices() switches the music
2767 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2768 * So when the ringtone playback is completed, how do we undo the same?
2769 *
2770 * We are relying on the out_set_parameters() call on deep-buffer output,
2771 * once the ringtone playback is ended.
2772 * NOTE: We should not check if the current devices are same as new devices.
2773 * Because select_devices() must be called to switch back the music
2774 * playback to headset.
2775 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002776 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002777 audio_devices_t new_dev = val;
2778 bool same_dev = out->devices == new_dev;
2779 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002780
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002781 if (output_drives_call(adev, out)) {
2782 if(!voice_is_in_call(adev)) {
2783 if (adev->mode == AUDIO_MODE_IN_CALL) {
2784 adev->current_call_output = out;
2785 ret = voice_start_call(adev);
2786 }
2787 } else {
2788 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002789 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002790 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002791 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002792
2793 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002794 if (!same_dev) {
2795 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302796 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2797 adev->perf_lock_opts,
2798 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002799 if (adev->adm_on_routing_change)
2800 adev->adm_on_routing_change(adev->adm_data,
2801 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002802 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002803 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302804 if (!same_dev)
2805 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002806 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002807 }
2808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002810 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002812
2813 if (out == adev->primary_output) {
2814 pthread_mutex_lock(&adev->lock);
2815 audio_extn_set_parameters(adev, parms);
2816 pthread_mutex_unlock(&adev->lock);
2817 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002818 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002819 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002820 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002821
2822 audio_extn_dts_create_state_notifier_node(out->usecase);
2823 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2824 popcount(out->channel_mask),
2825 out->playback_started);
2826
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002827 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002828 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002829
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302830 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2831 if (err >= 0) {
2832 strlcpy(out->profile, value, sizeof(out->profile));
2833 ALOGV("updating stream profile with value '%s'", out->profile);
2834 lock_output_stream(out);
2835 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2836 &adev->streams_output_cfg_list,
2837 out->devices, out->flags, out->format,
2838 out->sample_rate, out->bit_width,
2839 out->channel_mask, out->profile,
2840 &out->app_type_cfg);
2841 pthread_mutex_unlock(&out->lock);
2842 }
2843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302845error:
Eric Laurent994a6932013-07-17 11:51:42 -07002846 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 return ret;
2848}
2849
2850static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2851{
2852 struct stream_out *out = (struct stream_out *)stream;
2853 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002854 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 char value[256];
2856 struct str_parms *reply = str_parms_create();
2857 size_t i, j;
2858 int ret;
2859 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002860
2861 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002862 if (reply) {
2863 str_parms_destroy(reply);
2864 }
2865 if (query) {
2866 str_parms_destroy(query);
2867 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002868 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2869 return NULL;
2870 }
2871
Eric Laurent994a6932013-07-17 11:51:42 -07002872 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2874 if (ret >= 0) {
2875 value[0] = '\0';
2876 i = 0;
2877 while (out->supported_channel_masks[i] != 0) {
2878 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2879 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2880 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002881 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002883 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 first = false;
2885 break;
2886 }
2887 }
2888 i++;
2889 }
2890 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2891 str = str_parms_to_str(reply);
2892 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002893 voice_extn_out_get_parameters(out, query, reply);
2894 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002895 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002896 free(str);
2897 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002898 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002899 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002900
Alexy Joseph62142aa2015-11-16 15:10:34 -08002901
2902 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2903 if (ret >= 0) {
2904 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302905 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2906 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002907 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302908 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002909 } else {
2910 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302911 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002912 }
2913 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002914 if (str)
2915 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002916 str = str_parms_to_str(reply);
2917 }
2918
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002919 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2920 if (ret >= 0) {
2921 value[0] = '\0';
2922 i = 0;
2923 first = true;
2924 while (out->supported_formats[i] != 0) {
2925 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2926 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2927 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002928 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002929 }
2930 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2931 first = false;
2932 break;
2933 }
2934 }
2935 i++;
2936 }
2937 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002938 if (str)
2939 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002940 str = str_parms_to_str(reply);
2941 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002942
2943 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2944 if (ret >= 0) {
2945 value[0] = '\0';
2946 i = 0;
2947 first = true;
2948 while (out->supported_sample_rates[i] != 0) {
2949 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2950 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2951 if (!first) {
2952 strlcat(value, "|", sizeof(value));
2953 }
2954 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2955 first = false;
2956 break;
2957 }
2958 }
2959 i++;
2960 }
2961 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2962 if (str)
2963 free(str);
2964 str = str_parms_to_str(reply);
2965 }
2966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967 str_parms_destroy(query);
2968 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002969 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 return str;
2971}
2972
2973static uint32_t out_get_latency(const struct audio_stream_out *stream)
2974{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002975 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002977 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978
Alexy Josephaa54c872014-12-03 02:46:47 -08002979 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302980 lock_output_stream(out);
2981 latency = audio_extn_utils_compress_get_dsp_latency(out);
2982 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002983 } else if (out->realtime) {
2984 // since the buffer won't be filled up faster than realtime,
2985 // return a smaller number
2986 if (out->config.rate)
2987 period_ms = (out->af_period_multiplier * out->config.period_size *
2988 1000) / (out->config.rate);
2989 else
2990 period_ms = 0;
2991 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002992 } else {
2993 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002994 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002995 }
2996
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002997 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2998 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2999 latency += audio_extn_a2dp_get_encoder_latency();
3000
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303001 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003002 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003}
3004
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303005static float AmpToDb(float amplification)
3006{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303007 float db = DSD_VOLUME_MIN_DB;
3008 if (amplification > 0) {
3009 db = 20 * log10(amplification);
3010 if(db < DSD_VOLUME_MIN_DB)
3011 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303012 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303013 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303014}
3015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016static int out_set_volume(struct audio_stream_out *stream, float left,
3017 float right)
3018{
Eric Laurenta9024de2013-04-04 09:19:12 -07003019 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 int volume[2];
3021
Eric Laurenta9024de2013-04-04 09:19:12 -07003022 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3023 /* only take left channel into account: the API is for stereo anyway */
3024 out->muted = (left == 0.0f);
3025 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003026 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303027 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003028 /*
3029 * Set mute or umute on HDMI passthrough stream.
3030 * Only take left channel into account.
3031 * Mute is 0 and unmute 1
3032 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303033 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303034 } else if (out->format == AUDIO_FORMAT_DSD){
3035 char mixer_ctl_name[128] = "DSD Volume";
3036 struct audio_device *adev = out->dev;
3037 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3038
3039 if (!ctl) {
3040 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3041 __func__, mixer_ctl_name);
3042 return -EINVAL;
3043 }
3044 volume[0] = (int)(AmpToDb(left));
3045 volume[1] = (int)(AmpToDb(right));
3046 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3047 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003048 } else {
3049 char mixer_ctl_name[128];
3050 struct audio_device *adev = out->dev;
3051 struct mixer_ctl *ctl;
3052 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003053 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003055 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3056 "Compress Playback %d Volume", pcm_device_id);
3057 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3058 if (!ctl) {
3059 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3060 __func__, mixer_ctl_name);
3061 return -EINVAL;
3062 }
3063 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3064 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3065 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3066 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003068 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 return -ENOSYS;
3071}
3072
3073static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3074 size_t bytes)
3075{
3076 struct stream_out *out = (struct stream_out *)stream;
3077 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303078 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003079 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003081 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303082
Naresh Tanniru80659832014-06-04 18:17:56 +05303083 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003084
Dhananjay Kumarac341582017-02-23 23:42:25 +05303085 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303086 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303087 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3088 pthread_mutex_unlock(&out->lock);
3089 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303090 } else {
3091 /* increase written size during SSR to avoid mismatch
3092 * with the written frames count in AF
3093 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003094 // bytes per frame
3095 size_t bpf = audio_bytes_per_sample(out->format) *
3096 audio_channel_count_from_out_mask(out->channel_mask);
3097 if (bpf != 0)
3098 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303099 ALOGD(" %s: sound card is not active/SSR state", __func__);
3100 ret= -EIO;
3101 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303102 }
3103 }
3104
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303105 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303106 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3107 if (audio_bytes_per_sample(out->format) != 0)
3108 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3109 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303110 goto exit;
3111 }
3112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003114 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003115 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003116 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3117 ret = voice_extn_compress_voip_start_output_stream(out);
3118 else
3119 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003120 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003121 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003123 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 goto exit;
3125 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003126
3127 if (last_known_cal_step != -1) {
3128 ALOGD("%s: retry previous failed cal level set", __func__);
3129 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3130 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132
Ashish Jain81eb2a82015-05-13 10:52:34 +05303133 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003134 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303135 adev->is_channel_status_set = true;
3136 }
3137
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003138 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003139 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003140 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003141 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003142 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3143 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303144 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3145 ALOGD("copl(%p):send next track params in gapless", out);
3146 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3147 out->send_next_track_params = false;
3148 out->is_compr_metadata_avail = false;
3149 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003150 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303151 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303152 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003153
Ashish Jain83a6cc22016-06-28 14:34:17 +05303154 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303155 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303156 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303157 pthread_mutex_unlock(&out->lock);
3158 return -EINVAL;
3159 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303160 audio_format_t dst_format = out->hal_op_format;
3161 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303162
3163 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3164 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3165
Ashish Jain83a6cc22016-06-28 14:34:17 +05303166 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303167 dst_format,
3168 buffer,
3169 src_format,
3170 frames);
3171
Ashish Jain83a6cc22016-06-28 14:34:17 +05303172 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303173 bytes_to_write);
3174
3175 /*Convert written bytes in audio flinger format*/
3176 if (ret > 0)
3177 ret = ((ret * format_to_bitwidth_table[out->format]) /
3178 format_to_bitwidth_table[dst_format]);
3179 }
3180 } else
3181 ret = compress_write(out->compr, buffer, bytes);
3182
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303183 if (ret < 0)
3184 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303185 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303186 /*msg to cb thread only if non blocking write is enabled*/
3187 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303188 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003189 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303190 } else if (-ENETRESET == ret) {
3191 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3192 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3193 pthread_mutex_unlock(&out->lock);
3194 out_standby(&out->stream.common);
3195 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003196 }
Ashish Jain5106d362016-05-11 19:23:33 +05303197 if ( ret == (ssize_t)bytes && !out->non_blocking)
3198 out->written += bytes;
3199
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303200 /* Call compr start only when non-zero bytes of data is there to be rendered */
3201 if (!out->playback_started && ret > 0) {
3202 int status = compress_start(out->compr);
3203 if (status < 0) {
3204 ret = status;
3205 ALOGE("%s: compr start failed with err %d", __func__, errno);
3206 goto exit;
3207 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003208 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 out->playback_started = 1;
3210 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003211
3212 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3213 popcount(out->channel_mask),
3214 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003215 }
3216 pthread_mutex_unlock(&out->lock);
3217 return ret;
3218 } else {
3219 if (out->pcm) {
3220 if (out->muted)
3221 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003222
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303223 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003224
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003225 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003226
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003227 if (out->config.rate)
3228 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3229 out->config.rate;
3230
3231 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3232
3233 request_out_focus(out, ns);
3234
3235 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003236 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003237 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303238 out->convert_buffer != NULL) {
3239
3240 memcpy_by_audio_format(out->convert_buffer,
3241 out->hal_op_format,
3242 buffer,
3243 out->hal_ip_format,
3244 out->config.period_size * out->config.channels);
3245
3246 ret = pcm_write(out->pcm, out->convert_buffer,
3247 (out->config.period_size *
3248 out->config.channels *
3249 format_to_bitwidth_table[out->hal_op_format]));
3250 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003251 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303252 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003253
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003254 release_out_focus(out);
3255
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303256 if (ret < 0)
3257 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303258 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3259 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3260 else
3261 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 }
3264
3265exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303266 /* ToDo: There may be a corner case when SSR happens back to back during
3267 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303268 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303269 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303270 }
3271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 pthread_mutex_unlock(&out->lock);
3273
3274 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003275 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003276 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303277 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303278 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303279 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303280 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303281 out->standby = true;
3282 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303284 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3285 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3286 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 }
3288 return bytes;
3289}
3290
3291static int out_get_render_position(const struct audio_stream_out *stream,
3292 uint32_t *dsp_frames)
3293{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303295 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003296
3297 if (dsp_frames == NULL)
3298 return -EINVAL;
3299
3300 *dsp_frames = 0;
3301 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003302 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303303
3304 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3305 * this operation and adev_close_output_stream(where out gets reset).
3306 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303307 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303308 *dsp_frames = get_actual_pcm_frames_rendered(out);
3309 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3310 return 0;
3311 }
3312
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003313 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303314 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303315 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003316 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303317 if (ret < 0)
3318 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003319 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303320 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003321 }
3322 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303323 if (-ENETRESET == ret) {
3324 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3325 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3326 return -EINVAL;
3327 } else if(ret < 0) {
3328 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3329 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303330 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3331 /*
3332 * Handle corner case where compress session is closed during SSR
3333 * and timestamp is queried
3334 */
3335 ALOGE(" ERROR: sound card not active, return error");
3336 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303337 } else {
3338 return 0;
3339 }
Zhou Song32a556e2015-05-05 10:46:56 +08003340 } else if (audio_is_linear_pcm(out->format)) {
3341 *dsp_frames = out->written;
3342 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003343 } else
3344 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345}
3346
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003347static int out_add_audio_effect(const struct audio_stream *stream __unused,
3348 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349{
3350 return 0;
3351}
3352
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003353static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3354 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355{
3356 return 0;
3357}
3358
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003359static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3360 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361{
3362 return -EINVAL;
3363}
3364
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003365static int out_get_presentation_position(const struct audio_stream_out *stream,
3366 uint64_t *frames, struct timespec *timestamp)
3367{
3368 struct stream_out *out = (struct stream_out *)stream;
3369 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003370 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003371
Ashish Jain5106d362016-05-11 19:23:33 +05303372 /* below piece of code is not guarded against any lock because audioFliner serializes
3373 * this operation and adev_close_output_stream( where out gets reset).
3374 */
3375 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303376 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303377 *frames = get_actual_pcm_frames_rendered(out);
3378 /* this is the best we can do */
3379 clock_gettime(CLOCK_MONOTONIC, timestamp);
3380 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3381 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3382 return 0;
3383 }
3384
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003385 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003386
Ashish Jain5106d362016-05-11 19:23:33 +05303387 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3388 ret = compress_get_tstamp(out->compr, &dsp_frames,
3389 &out->sample_rate);
3390 ALOGVV("%s rendered frames %ld sample_rate %d",
3391 __func__, dsp_frames, out->sample_rate);
3392 *frames = dsp_frames;
3393 if (ret < 0)
3394 ret = -errno;
3395 if (-ENETRESET == ret) {
3396 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3397 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3398 ret = -EINVAL;
3399 } else
3400 ret = 0;
3401 /* this is the best we can do */
3402 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003403 } else {
3404 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003405 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003406 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3407 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003408 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003409 // This adjustment accounts for buffering after app processor.
3410 // It is based on estimated DSP latency per use case, rather than exact.
3411 signed_frames -=
3412 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3413
Eric Laurent949a0892013-09-20 09:20:13 -07003414 // It would be unusual for this value to be negative, but check just in case ...
3415 if (signed_frames >= 0) {
3416 *frames = signed_frames;
3417 ret = 0;
3418 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003419 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303420 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3421 *frames = out->written;
3422 clock_gettime(CLOCK_MONOTONIC, timestamp);
3423 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003424 }
3425 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003426 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003427 return ret;
3428}
3429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430static int out_set_callback(struct audio_stream_out *stream,
3431 stream_callback_t callback, void *cookie)
3432{
3433 struct stream_out *out = (struct stream_out *)stream;
3434
3435 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003436 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003437 out->offload_callback = callback;
3438 out->offload_cookie = cookie;
3439 pthread_mutex_unlock(&out->lock);
3440 return 0;
3441}
3442
3443static int out_pause(struct audio_stream_out* stream)
3444{
3445 struct stream_out *out = (struct stream_out *)stream;
3446 int status = -ENOSYS;
3447 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003448 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003449 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003450 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003451 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303452 struct audio_device *adev = out->dev;
3453 int snd_scard_state = get_snd_card_state(adev);
3454
3455 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3456 status = compress_pause(out->compr);
3457
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003458 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003459
Mingming Yin21854652016-04-13 11:54:02 -07003460 if (audio_extn_passthru_is_active()) {
3461 ALOGV("offload use case, pause passthru");
3462 audio_extn_passthru_on_pause(out);
3463 }
3464
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303465 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003466 audio_extn_dts_notify_playback_state(out->usecase, 0,
3467 out->sample_rate, popcount(out->channel_mask),
3468 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003469 }
3470 pthread_mutex_unlock(&out->lock);
3471 }
3472 return status;
3473}
3474
3475static int out_resume(struct audio_stream_out* stream)
3476{
3477 struct stream_out *out = (struct stream_out *)stream;
3478 int status = -ENOSYS;
3479 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003480 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003481 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003483 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303485 struct audio_device *adev = out->dev;
3486 int snd_scard_state = get_snd_card_state(adev);
3487
Mingming Yin21854652016-04-13 11:54:02 -07003488 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3489 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3490 pthread_mutex_lock(&out->dev->lock);
3491 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003492 pthread_mutex_unlock(&out->dev->lock);
3493 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303494 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003495 }
3496 if (!status) {
3497 out->offload_state = OFFLOAD_STATE_PLAYING;
3498 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303499 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003500 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3501 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 }
3503 pthread_mutex_unlock(&out->lock);
3504 }
3505 return status;
3506}
3507
3508static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3509{
3510 struct stream_out *out = (struct stream_out *)stream;
3511 int status = -ENOSYS;
3512 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003513 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003514 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003515 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3516 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3517 else
3518 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3519 pthread_mutex_unlock(&out->lock);
3520 }
3521 return status;
3522}
3523
3524static int out_flush(struct audio_stream_out* stream)
3525{
3526 struct stream_out *out = (struct stream_out *)stream;
3527 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003528 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003529 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003530 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003531 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3532 stop_compressed_output_l(out);
3533 out->written = 0;
3534 } else {
3535 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3536 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003537 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003538 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003539 return 0;
3540 }
3541 return -ENOSYS;
3542}
3543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544/** audio_stream_in implementation **/
3545static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3546{
3547 struct stream_in *in = (struct stream_in *)stream;
3548
3549 return in->config.rate;
3550}
3551
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003552static int in_set_sample_rate(struct audio_stream *stream __unused,
3553 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554{
3555 return -ENOSYS;
3556}
3557
3558static size_t in_get_buffer_size(const struct audio_stream *stream)
3559{
3560 struct stream_in *in = (struct stream_in *)stream;
3561
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003562 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3563 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003564 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3565 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303566 else if(audio_extn_cin_attached_usecase(in->usecase))
3567 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003568
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003569 return in->config.period_size * in->af_period_multiplier *
3570 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571}
3572
3573static uint32_t in_get_channels(const struct audio_stream *stream)
3574{
3575 struct stream_in *in = (struct stream_in *)stream;
3576
3577 return in->channel_mask;
3578}
3579
3580static audio_format_t in_get_format(const struct audio_stream *stream)
3581{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003582 struct stream_in *in = (struct stream_in *)stream;
3583
3584 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585}
3586
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003587static int in_set_format(struct audio_stream *stream __unused,
3588 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589{
3590 return -ENOSYS;
3591}
3592
3593static int in_standby(struct audio_stream *stream)
3594{
3595 struct stream_in *in = (struct stream_in *)stream;
3596 struct audio_device *adev = in->dev;
3597 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303598 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3599 stream, in->usecase, use_case_table[in->usecase]);
3600
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003601 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003602 if (!in->standby && in->is_st_session) {
3603 ALOGD("%s: sound trigger pcm stop lab", __func__);
3604 audio_extn_sound_trigger_stop_lab(in);
3605 in->standby = 1;
3606 }
3607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003609 if (adev->adm_deregister_stream)
3610 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3611
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003612 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003614 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3615 voice_extn_compress_voip_close_input_stream(stream);
3616 ALOGD("VOIP input entered standby");
3617 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303618 if (audio_extn_cin_attached_usecase(in->usecase))
3619 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003620 if (in->pcm) {
3621 pcm_close(in->pcm);
3622 in->pcm = NULL;
3623 }
3624 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003625 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003626 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 }
3628 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003629 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003630 return status;
3631}
3632
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003633static int in_dump(const struct audio_stream *stream __unused,
3634 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635{
3636 return 0;
3637}
3638
3639static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3640{
3641 struct stream_in *in = (struct stream_in *)stream;
3642 struct audio_device *adev = in->dev;
3643 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003644 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003645 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303647 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 parms = str_parms_create_str(kvpairs);
3649
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303650 if (!parms)
3651 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003652 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003653 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003654
3655 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3656 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 val = atoi(value);
3658 /* no audio source uses val == 0 */
3659 if ((in->source != val) && (val != 0)) {
3660 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003661 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3662 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3663 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003664 (in->config.rate == 8000 || in->config.rate == 16000 ||
3665 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003666 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003667 err = voice_extn_compress_voip_open_input_stream(in);
3668 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003669 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003670 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003671 }
3672 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 }
3674 }
3675
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003676 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3677 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003679 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 in->device = val;
3681 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003682 if (!in->standby && !in->is_st_session) {
3683 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003684 if (adev->adm_on_routing_change)
3685 adev->adm_on_routing_change(adev->adm_data,
3686 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003687 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003688 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 }
3690 }
3691
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303692 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3693 if (err >= 0) {
3694 strlcpy(in->profile, value, sizeof(in->profile));
3695 ALOGV("updating stream profile with value '%s'", in->profile);
3696 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3697 &adev->streams_input_cfg_list,
3698 in->device, in->flags, in->format,
3699 in->sample_rate, in->bit_width,
3700 in->profile, &in->app_type_cfg);
3701 }
3702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003704 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705
3706 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303707error:
Eric Laurent994a6932013-07-17 11:51:42 -07003708 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 return ret;
3710}
3711
3712static char* in_get_parameters(const struct audio_stream *stream,
3713 const char *keys)
3714{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003715 struct stream_in *in = (struct stream_in *)stream;
3716 struct str_parms *query = str_parms_create_str(keys);
3717 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003718 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003719
3720 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003721 if (reply) {
3722 str_parms_destroy(reply);
3723 }
3724 if (query) {
3725 str_parms_destroy(query);
3726 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003727 ALOGE("in_get_parameters: failed to create query or reply");
3728 return NULL;
3729 }
3730
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003731 ALOGV("%s: enter: keys - %s", __func__, keys);
3732
3733 voice_extn_in_get_parameters(in, query, reply);
3734
3735 str = str_parms_to_str(reply);
3736 str_parms_destroy(query);
3737 str_parms_destroy(reply);
3738
3739 ALOGV("%s: exit: returns - %s", __func__, str);
3740 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741}
3742
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003743static int in_set_gain(struct audio_stream_in *stream __unused,
3744 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745{
3746 return 0;
3747}
3748
3749static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3750 size_t bytes)
3751{
3752 struct stream_in *in = (struct stream_in *)stream;
3753 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303754 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303755 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303756 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003758 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303759
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003760 if (in->is_st_session) {
3761 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3762 /* Read from sound trigger HAL */
3763 audio_extn_sound_trigger_read(in, buffer, bytes);
3764 pthread_mutex_unlock(&in->lock);
3765 return bytes;
3766 }
3767
Ashish Jainbbce4322016-02-16 13:25:27 +05303768 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003769 ALOGD(" %s: sound card is not active/SSR state", __func__);
3770 ret= -EIO;;
3771 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303772 }
3773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003775 pthread_mutex_lock(&adev->lock);
3776 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3777 ret = voice_extn_compress_voip_start_input_stream(in);
3778 else
3779 ret = start_input_stream(in);
3780 pthread_mutex_unlock(&adev->lock);
3781 if (ret != 0) {
3782 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 }
3784 in->standby = 0;
3785 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003787 // what's the duration requested by the client?
3788 long ns = 0;
3789
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303790 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003791 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3792 in->config.rate;
3793
3794 request_in_focus(in, ns);
3795 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003796
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303797 if (audio_extn_cin_attached_usecase(in->usecase)) {
3798 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3799 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303800 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003801 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303802 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003803 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003804 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003805 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303806 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003807 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303808 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3809 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3810 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3811 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303812 ret = -EINVAL;
3813 goto exit;
3814 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303815 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303816 ret = -errno;
3817 }
3818 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303819 /* bytes read is always set to bytes for non compress usecases */
3820 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 }
3822
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003823 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 /*
3826 * Instead of writing zeroes here, we could trust the hardware
3827 * to always provide zeroes when muted.
3828 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303829 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3830 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831 memset(buffer, 0, bytes);
3832
3833exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303834 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303835 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003836 if (-ENETRESET == ret)
3837 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 pthread_mutex_unlock(&in->lock);
3840
3841 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303842 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303843 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303844 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303845 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303846 in->standby = true;
3847 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303848 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3849 bytes_read = bytes;
3850 memset(buffer, 0, bytes);
3851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003853 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303854 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303855 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303857 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858}
3859
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003860static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861{
3862 return 0;
3863}
3864
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003865static int add_remove_audio_effect(const struct audio_stream *stream,
3866 effect_handle_t effect,
3867 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003869 struct stream_in *in = (struct stream_in *)stream;
3870 int status = 0;
3871 effect_descriptor_t desc;
3872
3873 status = (*effect)->get_descriptor(effect, &desc);
3874 if (status != 0)
3875 return status;
3876
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003877 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003878 pthread_mutex_lock(&in->dev->lock);
3879 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3880 in->enable_aec != enable &&
3881 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3882 in->enable_aec = enable;
3883 if (!in->standby)
3884 select_devices(in->dev, in->usecase);
3885 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003886 if (in->enable_ns != enable &&
3887 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3888 in->enable_ns = enable;
3889 if (!in->standby)
3890 select_devices(in->dev, in->usecase);
3891 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003892 pthread_mutex_unlock(&in->dev->lock);
3893 pthread_mutex_unlock(&in->lock);
3894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895 return 0;
3896}
3897
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003898static int in_add_audio_effect(const struct audio_stream *stream,
3899 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900{
Eric Laurent994a6932013-07-17 11:51:42 -07003901 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003902 return add_remove_audio_effect(stream, effect, true);
3903}
3904
3905static int in_remove_audio_effect(const struct audio_stream *stream,
3906 effect_handle_t effect)
3907{
Eric Laurent994a6932013-07-17 11:51:42 -07003908 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003909 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910}
3911
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303912int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 audio_io_handle_t handle,
3914 audio_devices_t devices,
3915 audio_output_flags_t flags,
3916 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003917 struct audio_stream_out **stream_out,
3918 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919{
3920 struct audio_device *adev = (struct audio_device *)dev;
3921 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303922 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003923 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303926
3927 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3928 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003929 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303930 return -EINVAL;
3931 }
3932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3934
Mingming Yin3a941d42016-02-17 18:08:05 -08003935 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3936 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303937 devices, flags, &out->stream);
3938
3939
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003940 if (!out) {
3941 return -ENOMEM;
3942 }
3943
Haynes Mathew George204045b2015-02-25 20:32:03 -08003944 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003945 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003946 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948 if (devices == AUDIO_DEVICE_NONE)
3949 devices = AUDIO_DEVICE_OUT_SPEAKER;
3950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 out->flags = flags;
3952 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003953 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003954 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003955 out->sample_rate = config->sample_rate;
3956 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3957 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003958 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003959 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003960 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303961 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962
Mingming Yin3a941d42016-02-17 18:08:05 -08003963 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3964 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3965 pthread_mutex_lock(&adev->lock);
3966 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3967 ret = read_hdmi_sink_caps(out);
3968 pthread_mutex_unlock(&adev->lock);
3969 if (ret != 0) {
3970 if (ret == -ENOSYS) {
3971 /* ignore and go with default */
3972 ret = 0;
3973 } else {
3974 ALOGE("error reading hdmi sink caps");
3975 goto error_open;
3976 }
3977 }
3978 }
3979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303981 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003982 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003983 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003984 ret = voice_extn_compress_voip_open_output_stream(out);
3985 if (ret != 0) {
3986 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3987 __func__, ret);
3988 goto error_open;
3989 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003990 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05303991 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003992
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003993 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3994 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3995 ALOGE("%s: Unsupported Offload information", __func__);
3996 ret = -EINVAL;
3997 goto error_open;
3998 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003999
Mingming Yin3a941d42016-02-17 18:08:05 -08004000 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004001 if(config->offload_info.format == 0)
4002 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004003 if (config->offload_info.sample_rate == 0)
4004 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004005 }
4006
Mingming Yin90310102013-11-13 16:57:00 -08004007 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304008 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004009 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004010 ret = -EINVAL;
4011 goto error_open;
4012 }
4013
4014 out->compr_config.codec = (struct snd_codec *)
4015 calloc(1, sizeof(struct snd_codec));
4016
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004017 if (!out->compr_config.codec) {
4018 ret = -ENOMEM;
4019 goto error_open;
4020 }
4021
Dhananjay Kumarac341582017-02-23 23:42:25 +05304022 out->stream.pause = out_pause;
4023 out->stream.resume = out_resume;
4024 out->stream.flush = out_flush;
4025 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004026 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004027 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304028 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004029 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304030 } else {
4031 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4032 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004033 }
vivek mehta446c3962015-09-14 10:57:35 -07004034
4035 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004036 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4037 config->format == 0 && config->sample_rate == 0 &&
4038 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004039 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004040 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4041 } else {
4042 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4043 ret = -EEXIST;
4044 goto error_open;
4045 }
vivek mehta446c3962015-09-14 10:57:35 -07004046 }
4047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048 if (config->offload_info.channel_mask)
4049 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004050 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004051 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004052 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004053 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304054 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004055 ret = -EINVAL;
4056 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004057 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004058
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004059 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004060 out->sample_rate = config->offload_info.sample_rate;
4061
Mingming Yin3ee55c62014-08-04 14:23:35 -07004062 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004063
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304064 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4065 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4066 audio_extn_dolby_send_ddp_endp_params(adev);
4067 audio_extn_dolby_set_dmid(adev);
4068 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004069
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004070 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004071 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 out->compr_config.codec->bit_rate =
4073 config->offload_info.bit_rate;
4074 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304075 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004076 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304077 /* Update bit width only for non passthrough usecases.
4078 * For passthrough usecases, the output will always be opened @16 bit
4079 */
4080 if (!audio_extn_passthru_is_passthrough_stream(out))
4081 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004082 /*TODO: Do we need to change it for passthrough */
4083 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084
Manish Dewangana6fc5442015-08-24 20:30:31 +05304085 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4086 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304087 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304088 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304089 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4090 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304091
4092 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4093 AUDIO_FORMAT_PCM) {
4094
4095 /*Based on platform support, configure appropriate alsa format for corresponding
4096 *hal input format.
4097 */
4098 out->compr_config.codec->format = hal_format_to_alsa(
4099 config->offload_info.format);
4100
Ashish Jain83a6cc22016-06-28 14:34:17 +05304101 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304102 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304103 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304104
Dhananjay Kumarac341582017-02-23 23:42:25 +05304105 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304106 *hal input format and alsa format might differ based on platform support.
4107 */
4108 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304109 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304110
4111 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4112
4113 /* Check if alsa session is configured with the same format as HAL input format,
4114 * if not then derive correct fragment size needed to accomodate the
4115 * conversion of HAL input format to alsa format.
4116 */
4117 audio_extn_utils_update_direct_pcm_fragment_size(out);
4118
4119 /*if hal input and output fragment size is different this indicates HAL input format is
4120 *not same as the alsa format
4121 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304122 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304123 /*Allocate a buffer to convert input data to the alsa configured format.
4124 *size of convert buffer is equal to the size required to hold one fragment size
4125 *worth of pcm data, this is because flinger does not write more than fragment_size
4126 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304127 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4128 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304129 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4130 ret = -ENOMEM;
4131 goto error_open;
4132 }
4133 }
4134 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4135 out->compr_config.fragment_size =
4136 audio_extn_passthru_get_buffer_size(&config->offload_info);
4137 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4138 } else {
4139 out->compr_config.fragment_size =
4140 platform_get_compress_offload_buffer_size(&config->offload_info);
4141 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4142 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004143
Amit Shekhar6f461b12014-08-01 14:52:58 -07004144 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304145 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004146
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304147 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4148 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4149 }
4150
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004151 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4152 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004153
Manish Dewangan69426c82017-01-30 17:35:36 +05304154 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4155 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4156 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4157 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4158 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4159 } else {
4160 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4161 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004162
Manish Dewangan27346042017-03-01 12:56:12 +05304163 memset(&out->render_window, 0,
4164 sizeof(struct audio_out_render_window_param));
4165
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004166 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304167 out->send_next_track_params = false;
4168 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004169 out->offload_state = OFFLOAD_STATE_IDLE;
4170 out->playback_started = 0;
4171
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004172 audio_extn_dts_create_state_notifier_node(out->usecase);
4173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004174 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4175 __func__, config->offload_info.version,
4176 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304177
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304178 /* Check if DSD audio format is supported in codec
4179 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304180 */
4181
4182 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304183 (!platform_check_codec_dsd_support(adev->platform) ||
4184 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304185 ret = -EINVAL;
4186 goto error_open;
4187 }
4188
Ashish Jain5106d362016-05-11 19:23:33 +05304189 /* Disable gapless if any of the following is true
4190 * passthrough playback
4191 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304192 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304193 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304194 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304195 (config->format == AUDIO_FORMAT_DSD) ||
4196 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304197 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304198 check_and_set_gapless_mode(adev, false);
4199 } else
4200 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004201
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304202 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004203 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4204 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304205 if (config->format == AUDIO_FORMAT_DSD) {
4206 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4207 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4208 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004209
4210 create_offload_callback_thread(out);
4211
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004212 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304213 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004214 if (ret != 0) {
4215 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4216 __func__, ret);
4217 goto error_open;
4218 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004219 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4220 if (config->sample_rate == 0)
4221 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4222 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4223 config->sample_rate != 8000) {
4224 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4225 ret = -EINVAL;
4226 goto error_open;
4227 }
4228 out->sample_rate = config->sample_rate;
4229 out->config.rate = config->sample_rate;
4230 if (config->format == AUDIO_FORMAT_DEFAULT)
4231 config->format = AUDIO_FORMAT_PCM_16_BIT;
4232 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4233 config->format = AUDIO_FORMAT_PCM_16_BIT;
4234 ret = -EINVAL;
4235 goto error_open;
4236 }
4237 out->format = config->format;
4238 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4239 out->config = pcm_config_afe_proxy_playback;
4240 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004241 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304242 unsigned int channels = 0;
4243 /*Update config params to default if not set by the caller*/
4244 if (config->sample_rate == 0)
4245 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4246 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4247 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4248 if (config->format == AUDIO_FORMAT_DEFAULT)
4249 config->format = AUDIO_FORMAT_PCM_16_BIT;
4250
4251 channels = audio_channel_count_from_out_mask(out->channel_mask);
4252
Ashish Jain83a6cc22016-06-28 14:34:17 +05304253 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4254 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004255 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4256 out->flags);
4257 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304258 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4259 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4260 out->config = pcm_config_low_latency;
4261 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4262 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4263 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304264 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4265 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4266 if (out->config.period_size <= 0) {
4267 ALOGE("Invalid configuration period size is not valid");
4268 ret = -EINVAL;
4269 goto error_open;
4270 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304271 } else {
4272 /* primary path is the default path selected if no other outputs are available/suitable */
4273 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4274 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4275 }
4276 out->hal_ip_format = format = out->format;
4277 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4278 out->hal_op_format = pcm_format_to_hal(out->config.format);
4279 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4280 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004281 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304282 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304283 if (out->hal_ip_format != out->hal_op_format) {
4284 uint32_t buffer_size = out->config.period_size *
4285 format_to_bitwidth_table[out->hal_op_format] *
4286 out->config.channels;
4287 out->convert_buffer = calloc(1, buffer_size);
4288 if (out->convert_buffer == NULL){
4289 ALOGE("Allocation failed for convert buffer for size %d",
4290 out->compr_config.fragment_size);
4291 ret = -ENOMEM;
4292 goto error_open;
4293 }
4294 ALOGD("Convert buffer allocated of size %d", buffer_size);
4295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 }
4297
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004298 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4299 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304300
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004301 /* TODO remove this hardcoding and check why width is zero*/
4302 if (out->bit_width == 0)
4303 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304304 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004305 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304306 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304307 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304308 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004309 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4310 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4311 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004312 if(adev->primary_output == NULL)
4313 adev->primary_output = out;
4314 else {
4315 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004316 ret = -EEXIST;
4317 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004318 }
4319 }
4320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 /* Check if this usecase is already existing */
4322 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004323 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4324 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004327 ret = -EEXIST;
4328 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331 pthread_mutex_unlock(&adev->lock);
4332
4333 out->stream.common.get_sample_rate = out_get_sample_rate;
4334 out->stream.common.set_sample_rate = out_set_sample_rate;
4335 out->stream.common.get_buffer_size = out_get_buffer_size;
4336 out->stream.common.get_channels = out_get_channels;
4337 out->stream.common.get_format = out_get_format;
4338 out->stream.common.set_format = out_set_format;
4339 out->stream.common.standby = out_standby;
4340 out->stream.common.dump = out_dump;
4341 out->stream.common.set_parameters = out_set_parameters;
4342 out->stream.common.get_parameters = out_get_parameters;
4343 out->stream.common.add_audio_effect = out_add_audio_effect;
4344 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4345 out->stream.get_latency = out_get_latency;
4346 out->stream.set_volume = out_set_volume;
4347 out->stream.write = out_write;
4348 out->stream.get_render_position = out_get_render_position;
4349 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004350 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004352 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004354 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004355 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356
4357 config->format = out->stream.common.get_format(&out->stream.common);
4358 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4359 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4360
4361 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304362 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004363 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004364
4365 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4366 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4367 popcount(out->channel_mask), out->playback_started);
4368
Eric Laurent994a6932013-07-17 11:51:42 -07004369 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004371
4372error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304373 if (out->convert_buffer)
4374 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004375 free(out);
4376 *stream_out = NULL;
4377 ALOGD("%s: exit: ret %d", __func__, ret);
4378 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379}
4380
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304381void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382 struct audio_stream_out *stream)
4383{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004384 struct stream_out *out = (struct stream_out *)stream;
4385 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004386 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004387
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304388 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4389
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004390 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304391 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004392 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304393 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004394 if(ret != 0)
4395 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4396 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004397 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004398 out_standby(&stream->common);
4399
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004400 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004401 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004402 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004403 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004404 if (out->compr_config.codec != NULL)
4405 free(out->compr_config.codec);
4406 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004407
Ashish Jain83a6cc22016-06-28 14:34:17 +05304408 if (out->convert_buffer != NULL) {
4409 free(out->convert_buffer);
4410 out->convert_buffer = NULL;
4411 }
4412
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004413 if (adev->voice_tx_output == out)
4414 adev->voice_tx_output = NULL;
4415
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304416 if (adev->primary_output == out)
4417 adev->primary_output = NULL;
4418
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004419 pthread_cond_destroy(&out->cond);
4420 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004422 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423}
4424
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004425static void close_compress_sessions(struct audio_device *adev)
4426{
Mingming Yin7b762e72015-03-04 13:47:32 -08004427 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304428 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004429 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004430 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304431
4432 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004433 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304434 if (is_offload_usecase(usecase->id)) {
4435 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004436 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4437 out = usecase->stream.out;
4438 pthread_mutex_unlock(&adev->lock);
4439 out_standby(&out->stream.common);
4440 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004441 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004442 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304443 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004444 }
4445 pthread_mutex_unlock(&adev->lock);
4446}
4447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004448static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4449{
4450 struct audio_device *adev = (struct audio_device *)dev;
4451 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004452 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004453 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004454 int ret;
4455 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004456
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004457 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304460 if (!parms)
4461 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004462 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4463 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304464 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304465 if (strstr(snd_card_status, "OFFLINE")) {
4466 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304467 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004468 //close compress sessions on OFFLINE status
4469 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304470 } else if (strstr(snd_card_status, "ONLINE")) {
4471 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304472 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004473 //send dts hpx license if enabled
4474 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304475 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304476 }
4477
4478 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004479 status = voice_set_parameters(adev, parms);
4480 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004481 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004483 status = platform_set_parameters(adev->platform, parms);
4484 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004485 goto done;
4486
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004487 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4488 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004489 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4491 adev->bluetooth_nrec = true;
4492 else
4493 adev->bluetooth_nrec = false;
4494 }
4495
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004496 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4497 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4499 adev->screen_off = false;
4500 else
4501 adev->screen_off = true;
4502 }
4503
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004504 ret = str_parms_get_int(parms, "rotation", &val);
4505 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004506 bool reverse_speakers = false;
4507 switch(val) {
4508 // FIXME: note that the code below assumes that the speakers are in the correct placement
4509 // relative to the user when the device is rotated 90deg from its default rotation. This
4510 // assumption is device-specific, not platform-specific like this code.
4511 case 270:
4512 reverse_speakers = true;
4513 break;
4514 case 0:
4515 case 90:
4516 case 180:
4517 break;
4518 default:
4519 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004520 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004521 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004522 if (status == 0) {
4523 if (adev->speaker_lr_swap != reverse_speakers) {
4524 adev->speaker_lr_swap = reverse_speakers;
4525 // only update the selected device if there is active pcm playback
4526 struct audio_usecase *usecase;
4527 struct listnode *node;
4528 list_for_each(node, &adev->usecase_list) {
4529 usecase = node_to_item(node, struct audio_usecase, list);
4530 if (usecase->type == PCM_PLAYBACK) {
4531 select_devices(adev, usecase->id);
4532 break;
4533 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004534 }
4535 }
4536 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004537 }
4538
Mingming Yin514a8bc2014-07-29 15:22:21 -07004539 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4540 if (ret >= 0) {
4541 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4542 adev->bt_wb_speech_enabled = true;
4543 else
4544 adev->bt_wb_speech_enabled = false;
4545 }
4546
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004547 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4548 if (ret >= 0) {
4549 val = atoi(value);
4550 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004551 ALOGV("cache new ext disp type and edid");
4552 ret = platform_get_ext_disp_type(adev->platform);
4553 if (ret < 0) {
4554 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004555 status = ret;
4556 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004557 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004558 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004559 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004560 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004561 /*
4562 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4563 * Per AudioPolicyManager, USB device is higher priority than WFD.
4564 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4565 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4566 * starting voice call on USB
4567 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004568 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4569 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004570 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4571 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004572 }
vivek mehta344576a2016-04-12 18:56:03 -07004573 ALOGV("detected USB connect .. disable proxy");
4574 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004575 }
4576 }
4577
4578 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4579 if (ret >= 0) {
4580 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004581 /*
4582 * The HDMI / Displayport disconnect handling has been moved to
4583 * audio extension to ensure that its parameters are not
4584 * invalidated prior to updating sysfs of the disconnect event
4585 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4586 */
4587 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004588 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004589 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4590 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304591 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4592 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004593 }
vivek mehta344576a2016-04-12 18:56:03 -07004594 ALOGV("detected USB disconnect .. enable proxy");
4595 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004596 }
4597 }
4598
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304599 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4600 if (ret >= 0) {
4601 struct audio_usecase *usecase;
4602 struct listnode *node;
4603 list_for_each(node, &adev->usecase_list) {
4604 usecase = node_to_item(node, struct audio_usecase, list);
4605 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004606 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304607 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304608 lock_output_stream(usecase->stream.out);
4609 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304610 //force device switch to re configure encoder
4611 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304612 audio_extn_a2dp_set_handoff_mode(false);
4613 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304614 break;
4615 }
4616 }
4617 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004618
4619 //handle vr audio setparam
4620 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4621 value, sizeof(value));
4622 if (ret >= 0) {
4623 ALOGI("Setting vr mode to be %s", value);
4624 if (!strncmp(value, "true", 4)) {
4625 adev->vr_audio_mode_enabled = true;
4626 ALOGI("Setting vr mode to true");
4627 } else if (!strncmp(value, "false", 5)) {
4628 adev->vr_audio_mode_enabled = false;
4629 ALOGI("Setting vr mode to false");
4630 } else {
4631 ALOGI("wrong vr mode set");
4632 }
4633 }
4634
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304635 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004636done:
4637 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004638 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304639error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004640 ALOGV("%s: exit with code(%d)", __func__, status);
4641 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642}
4643
4644static char* adev_get_parameters(const struct audio_hw_device *dev,
4645 const char *keys)
4646{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004647 struct audio_device *adev = (struct audio_device *)dev;
4648 struct str_parms *reply = str_parms_create();
4649 struct str_parms *query = str_parms_create_str(keys);
4650 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304651 char value[256] = {0};
4652 int ret = 0;
4653
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004654 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004655 if (reply) {
4656 str_parms_destroy(reply);
4657 }
4658 if (query) {
4659 str_parms_destroy(query);
4660 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004661 ALOGE("adev_get_parameters: failed to create query or reply");
4662 return NULL;
4663 }
4664
Naresh Tannirud7205b62014-06-20 02:54:48 +05304665 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4666 sizeof(value));
4667 if (ret >=0) {
4668 int val = 1;
4669 pthread_mutex_lock(&adev->snd_card_status.lock);
4670 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4671 val = 0;
4672 pthread_mutex_unlock(&adev->snd_card_status.lock);
4673 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4674 goto exit;
4675 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004676 //handle vr audio getparam
4677
4678 ret = str_parms_get_str(query,
4679 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4680 value, sizeof(value));
4681
4682 if (ret >= 0) {
4683 bool vr_audio_enabled = false;
4684 pthread_mutex_lock(&adev->lock);
4685 vr_audio_enabled = adev->vr_audio_mode_enabled;
4686 pthread_mutex_unlock(&adev->lock);
4687
4688 ALOGI("getting vr mode to %d", vr_audio_enabled);
4689
4690 if (vr_audio_enabled) {
4691 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4692 "true");
4693 goto exit;
4694 } else {
4695 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4696 "false");
4697 goto exit;
4698 }
4699 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004700
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004701 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004702 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004703 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004704 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304705 pthread_mutex_unlock(&adev->lock);
4706
Naresh Tannirud7205b62014-06-20 02:54:48 +05304707exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004708 str = str_parms_to_str(reply);
4709 str_parms_destroy(query);
4710 str_parms_destroy(reply);
4711
4712 ALOGV("%s: exit: returns - %s", __func__, str);
4713 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714}
4715
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004716static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004717{
4718 return 0;
4719}
4720
4721static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4722{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004723 int ret;
4724 struct audio_device *adev = (struct audio_device *)dev;
4725 pthread_mutex_lock(&adev->lock);
4726 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004727 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004728 pthread_mutex_unlock(&adev->lock);
4729 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730}
4731
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004732static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4733 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004734{
4735 return -ENOSYS;
4736}
4737
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004738static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4739 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740{
4741 return -ENOSYS;
4742}
4743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004744static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4745 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746{
4747 return -ENOSYS;
4748}
4749
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004750static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4751 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752{
4753 return -ENOSYS;
4754}
4755
4756static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4757{
4758 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760 pthread_mutex_lock(&adev->lock);
4761 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004762 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004764 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004765 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004766 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004767 adev->current_call_output = NULL;
4768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 }
4770 pthread_mutex_unlock(&adev->lock);
4771 return 0;
4772}
4773
4774static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4775{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004776 int ret;
4777
4778 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004779 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004780 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4781 pthread_mutex_unlock(&adev->lock);
4782
4783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784}
4785
4786static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4787{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004788 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789 return 0;
4790}
4791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004792static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793 const struct audio_config *config)
4794{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004795 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004797 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4798 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799}
4800
4801static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004802 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004803 audio_devices_t devices,
4804 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004805 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304806 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004807 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004808 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004809{
4810 struct audio_device *adev = (struct audio_device *)dev;
4811 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004812 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004813 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004814 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304815 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304818 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4819 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304821 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822
4823 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004824
4825 if (!in) {
4826 ALOGE("failed to allocate input stream");
4827 return -ENOMEM;
4828 }
4829
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304830 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304831 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4832 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004833 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004834 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004836 in->stream.common.get_sample_rate = in_get_sample_rate;
4837 in->stream.common.set_sample_rate = in_set_sample_rate;
4838 in->stream.common.get_buffer_size = in_get_buffer_size;
4839 in->stream.common.get_channels = in_get_channels;
4840 in->stream.common.get_format = in_get_format;
4841 in->stream.common.set_format = in_set_format;
4842 in->stream.common.standby = in_standby;
4843 in->stream.common.dump = in_dump;
4844 in->stream.common.set_parameters = in_set_parameters;
4845 in->stream.common.get_parameters = in_get_parameters;
4846 in->stream.common.add_audio_effect = in_add_audio_effect;
4847 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4848 in->stream.set_gain = in_set_gain;
4849 in->stream.read = in_read;
4850 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4851
4852 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004853 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855 in->standby = 1;
4856 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004857 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004858 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304860 in->usecase = USECASE_AUDIO_RECORD;
4861 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4862 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4863 is_low_latency = true;
4864#if LOW_LATENCY_CAPTURE_USE_CASE
4865 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4866#endif
4867 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4868 }
4869
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004870 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004871 if (in->realtime) {
4872 in->config = pcm_config_audio_capture_rt;
4873 in->sample_rate = in->config.rate;
4874 in->af_period_multiplier = af_period_multiplier;
4875 } else {
4876 in->config = pcm_config_audio_capture;
4877 in->config.rate = config->sample_rate;
4878 in->sample_rate = config->sample_rate;
4879 in->af_period_multiplier = 1;
4880 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304881 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004882
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304883 /* restrict 24 bit capture for unprocessed source only
4884 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4885 */
4886 if (config->format == AUDIO_FORMAT_DEFAULT) {
4887 config->format = AUDIO_FORMAT_PCM_16_BIT;
4888 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4889 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4890 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4891 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4892 bool ret_error = false;
4893 in->bit_width = 24;
4894 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4895 from HAL is 24_packed and 8_24
4896 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4897 24_packed return error indicating supported format is 24_packed
4898 *> In case of any other source requesting 24 bit or float return error
4899 indicating format supported is 16 bit only.
4900
4901 on error flinger will retry with supported format passed
4902 */
4903 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4904 (source != AUDIO_SOURCE_CAMCORDER)) {
4905 config->format = AUDIO_FORMAT_PCM_16_BIT;
4906 if (config->sample_rate > 48000)
4907 config->sample_rate = 48000;
4908 ret_error = true;
4909 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4910 in->config.format = PCM_FORMAT_S24_3LE;
4911 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4912 in->config.format = PCM_FORMAT_S24_LE;
4913 } else {
4914 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4915 ret_error = true;
4916 }
4917
4918 if (ret_error) {
4919 ret = -EINVAL;
4920 goto err_open;
4921 }
4922 }
4923
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304924 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304925 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4926 (adev->mode != AUDIO_MODE_IN_CALL)) {
4927 ret = -EINVAL;
4928 goto err_open;
4929 }
4930
4931 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4932 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004933 if (config->sample_rate == 0)
4934 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4935 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4936 config->sample_rate != 8000) {
4937 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4938 ret = -EINVAL;
4939 goto err_open;
4940 }
4941 if (config->format == AUDIO_FORMAT_DEFAULT)
4942 config->format = AUDIO_FORMAT_PCM_16_BIT;
4943 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4944 config->format = AUDIO_FORMAT_PCM_16_BIT;
4945 ret = -EINVAL;
4946 goto err_open;
4947 }
4948
4949 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4950 in->config = pcm_config_afe_proxy_record;
4951 in->config.channels = channel_count;
4952 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304953 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304954 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4955 in, config, &channel_mask_updated)) {
4956 if (channel_mask_updated == true) {
4957 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4958 __func__, config->channel_mask);
4959 ret = -EINVAL;
4960 goto err_open;
4961 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304962 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004963 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004964 audio_extn_compr_cap_format_supported(config->format) &&
4965 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004966 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304967 } else if (audio_extn_cin_applicable_stream(in)) {
4968 ret = audio_extn_cin_configure_input_stream(in);
4969 if (ret)
4970 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004971 } else {
4972 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004973 if (!in->realtime) {
4974 in->format = config->format;
4975 frame_size = audio_stream_in_frame_size(&in->stream);
4976 buffer_size = get_input_buffer_size(config->sample_rate,
4977 config->format,
4978 channel_count,
4979 is_low_latency);
4980 in->config.period_size = buffer_size / frame_size;
4981 }
4982
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004983 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004984 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004985 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004986 (in->config.rate == 8000 || in->config.rate == 16000 ||
4987 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004988 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4989 voice_extn_compress_voip_open_input_stream(in);
4990 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004991 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304993 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4994 &adev->streams_input_cfg_list,
4995 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304996 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304997
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004998 /* This stream could be for sound trigger lab,
4999 get sound trigger pcm if present */
5000 audio_extn_sound_trigger_check_and_get_session(in);
5001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005003 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005004 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005
5006err_open:
5007 free(in);
5008 *stream_in = NULL;
5009 return ret;
5010}
5011
5012static void adev_close_input_stream(struct audio_hw_device *dev,
5013 struct audio_stream_in *stream)
5014{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005015 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005016 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005017 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305018
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305019 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005020
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305021 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005022 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305023
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005024 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305025 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005026 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305027 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005028 if (ret != 0)
5029 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5030 __func__, ret);
5031 } else
5032 in_standby(&stream->common);
5033
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005034 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005035 audio_extn_ssr_deinit();
5036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305038 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005039 audio_extn_compr_cap_format_supported(in->config.format))
5040 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305041
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305042 if (audio_extn_cin_attached_usecase(in->usecase))
5043 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005044
Mingming Yinfd7607b2016-01-22 12:48:44 -08005045 if (in->is_st_session) {
5046 ALOGV("%s: sound trigger pcm stop lab", __func__);
5047 audio_extn_sound_trigger_stop_lab(in);
5048 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005049 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050 return;
5051}
5052
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005053static int adev_dump(const audio_hw_device_t *device __unused,
5054 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055{
5056 return 0;
5057}
5058
5059static int adev_close(hw_device_t *device)
5060{
5061 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005062
5063 if (!adev)
5064 return 0;
5065
5066 pthread_mutex_lock(&adev_init_lock);
5067
5068 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005069 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005070 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305071 audio_extn_utils_release_streams_cfg_lists(
5072 &adev->streams_output_cfg_list,
5073 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305074 if (audio_extn_qaf_is_enabled())
5075 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005076 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005077 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005078 free(adev->snd_dev_ref_cnt);
5079 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005080 if (adev->adm_deinit)
5081 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305082 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005083 free(device);
5084 adev = NULL;
5085 }
5086 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005088 return 0;
5089}
5090
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005091/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5092 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5093 * just that it _might_ work.
5094 */
5095static int period_size_is_plausible_for_low_latency(int period_size)
5096{
5097 switch (period_size) {
5098 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005099 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005100 case 240:
5101 case 320:
5102 case 480:
5103 return 1;
5104 default:
5105 return 0;
5106 }
5107}
5108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005109static int adev_open(const hw_module_t *module, const char *name,
5110 hw_device_t **device)
5111{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305112 int ret;
5113
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005114 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5116
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005117 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005118 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005119 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005120 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005121 ALOGD("%s: returning existing instance of adev", __func__);
5122 ALOGD("%s: exit", __func__);
5123 pthread_mutex_unlock(&adev_init_lock);
5124 return 0;
5125 }
5126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127 adev = calloc(1, sizeof(struct audio_device));
5128
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005129 if (!adev) {
5130 pthread_mutex_unlock(&adev_init_lock);
5131 return -ENOMEM;
5132 }
5133
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005134 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005136 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5137 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5138 adev->device.common.module = (struct hw_module_t *)module;
5139 adev->device.common.close = adev_close;
5140
5141 adev->device.init_check = adev_init_check;
5142 adev->device.set_voice_volume = adev_set_voice_volume;
5143 adev->device.set_master_volume = adev_set_master_volume;
5144 adev->device.get_master_volume = adev_get_master_volume;
5145 adev->device.set_master_mute = adev_set_master_mute;
5146 adev->device.get_master_mute = adev_get_master_mute;
5147 adev->device.set_mode = adev_set_mode;
5148 adev->device.set_mic_mute = adev_set_mic_mute;
5149 adev->device.get_mic_mute = adev_get_mic_mute;
5150 adev->device.set_parameters = adev_set_parameters;
5151 adev->device.get_parameters = adev_get_parameters;
5152 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5153 adev->device.open_output_stream = adev_open_output_stream;
5154 adev->device.close_output_stream = adev_close_output_stream;
5155 adev->device.open_input_stream = adev_open_input_stream;
5156 adev->device.close_input_stream = adev_close_input_stream;
5157 adev->device.dump = adev_dump;
5158
5159 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005161 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005162 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005163 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005165 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005166 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005167 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005168 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005169 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005170 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005171 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005172 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305173 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305174 adev->perf_lock_opts[0] = 0x101;
5175 adev->perf_lock_opts[1] = 0x20E;
5176 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305177
5178 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5179 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005181 adev->platform = platform_init(adev);
5182 if (!adev->platform) {
5183 free(adev->snd_dev_ref_cnt);
5184 free(adev);
5185 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5186 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005187 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305188 pthread_mutex_destroy(&adev->lock);
5189 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005190 return -EINVAL;
5191 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005192
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305193 if (audio_extn_qaf_is_enabled()) {
5194 ret = audio_extn_qaf_init(adev);
5195 if (ret < 0) {
5196 free(adev);
5197 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5198 *device = NULL;
5199 pthread_mutex_unlock(&adev_init_lock);
5200 pthread_mutex_destroy(&adev->lock);
5201 return ret;
5202 }
5203
5204 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5205 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5206 }
5207
Naresh Tanniru4c630392014-05-12 01:05:52 +05305208 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5209
Eric Laurentc4aef752013-09-12 17:45:53 -07005210 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5211 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5212 if (adev->visualizer_lib == NULL) {
5213 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5214 } else {
5215 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5216 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005217 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005218 "visualizer_hal_start_output");
5219 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005220 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005221 "visualizer_hal_stop_output");
5222 }
5223 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305224 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005225 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005226 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005227 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005228
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005229 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5230 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5231 if (adev->offload_effects_lib == NULL) {
5232 ALOGE("%s: DLOPEN failed for %s", __func__,
5233 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5234 } else {
5235 ALOGV("%s: DLOPEN successful for %s", __func__,
5236 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5237 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305238 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005239 "offload_effects_bundle_hal_start_output");
5240 adev->offload_effects_stop_output =
5241 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5242 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005243 adev->offload_effects_set_hpx_state =
5244 (int (*)(bool))dlsym(adev->offload_effects_lib,
5245 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305246 adev->offload_effects_get_parameters =
5247 (void (*)(struct str_parms *, struct str_parms *))
5248 dlsym(adev->offload_effects_lib,
5249 "offload_effects_bundle_get_parameters");
5250 adev->offload_effects_set_parameters =
5251 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5252 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005253 }
5254 }
5255
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005256 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5257 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5258 if (adev->adm_lib == NULL) {
5259 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5260 } else {
5261 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5262 adev->adm_init = (adm_init_t)
5263 dlsym(adev->adm_lib, "adm_init");
5264 adev->adm_deinit = (adm_deinit_t)
5265 dlsym(adev->adm_lib, "adm_deinit");
5266 adev->adm_register_input_stream = (adm_register_input_stream_t)
5267 dlsym(adev->adm_lib, "adm_register_input_stream");
5268 adev->adm_register_output_stream = (adm_register_output_stream_t)
5269 dlsym(adev->adm_lib, "adm_register_output_stream");
5270 adev->adm_deregister_stream = (adm_deregister_stream_t)
5271 dlsym(adev->adm_lib, "adm_deregister_stream");
5272 adev->adm_request_focus = (adm_request_focus_t)
5273 dlsym(adev->adm_lib, "adm_request_focus");
5274 adev->adm_abandon_focus = (adm_abandon_focus_t)
5275 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005276 adev->adm_set_config = (adm_set_config_t)
5277 dlsym(adev->adm_lib, "adm_set_config");
5278 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5279 dlsym(adev->adm_lib, "adm_request_focus_v2");
5280 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5281 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5282 adev->adm_on_routing_change = (adm_on_routing_change_t)
5283 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005284 }
5285 }
5286
Mingming Yin514a8bc2014-07-29 15:22:21 -07005287 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005288 //initialize this to false for now,
5289 //this will be set to true through set param
5290 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005291
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005292 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005293 *device = &adev->device.common;
5294
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305295 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5296 &adev->streams_output_cfg_list,
5297 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005298
Kiran Kandi910e1862013-10-29 13:29:42 -07005299 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005300
5301 char value[PROPERTY_VALUE_MAX];
5302 int trial;
5303 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5304 trial = atoi(value);
5305 if (period_size_is_plausible_for_low_latency(trial)) {
5306 pcm_config_low_latency.period_size = trial;
5307 pcm_config_low_latency.start_threshold = trial / 4;
5308 pcm_config_low_latency.avail_min = trial / 4;
5309 configured_low_latency_capture_period_size = trial;
5310 }
5311 }
5312 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5313 trial = atoi(value);
5314 if (period_size_is_plausible_for_low_latency(trial)) {
5315 configured_low_latency_capture_period_size = trial;
5316 }
5317 }
5318
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005319 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5320 af_period_multiplier = atoi(value);
5321 if (af_period_multiplier < 0)
5322 af_period_multiplier = 2;
5323 else if (af_period_multiplier > 4)
5324 af_period_multiplier = 4;
5325
5326 ALOGV("new period_multiplier = %d", af_period_multiplier);
5327 }
5328
vivek mehta446c3962015-09-14 10:57:35 -07005329 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005330 pthread_mutex_unlock(&adev_init_lock);
5331
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005332 if (adev->adm_init)
5333 adev->adm_data = adev->adm_init();
5334
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305335 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305336 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005337 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338 return 0;
5339}
5340
5341static struct hw_module_methods_t hal_module_methods = {
5342 .open = adev_open,
5343};
5344
5345struct audio_module HAL_MODULE_INFO_SYM = {
5346 .common = {
5347 .tag = HARDWARE_MODULE_TAG,
5348 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5349 .hal_api_version = HARDWARE_HAL_API_VERSION,
5350 .id = AUDIO_HARDWARE_MODULE_ID,
5351 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005352 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353 .methods = &hal_module_methods,
5354 },
5355};