blob: 68a552d59331bbd456a4fda9fcc74dd8beaae418 [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);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002108 if (send_callback && out->client_callback) {
2109 ALOGVV("%s: sending client_callback event %d", __func__, event);
2110 out->client_callback(event, NULL, out->client_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
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002365 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 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;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003434 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435
3436 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003437 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003438 out->client_callback = callback;
3439 out->client_cookie = cookie;
3440 if (out->adsp_hdlr_stream_handle) {
3441 ret = audio_extn_adsp_hdlr_stream_set_callback(
3442 out->adsp_hdlr_stream_handle,
3443 callback,
3444 cookie);
3445 if (ret)
3446 ALOGW("%s:adsp hdlr callback registration failed %d",
3447 __func__, ret);
3448 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003449 pthread_mutex_unlock(&out->lock);
3450 return 0;
3451}
3452
3453static int out_pause(struct audio_stream_out* stream)
3454{
3455 struct stream_out *out = (struct stream_out *)stream;
3456 int status = -ENOSYS;
3457 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003458 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003459 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003460 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003461 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303462 struct audio_device *adev = out->dev;
3463 int snd_scard_state = get_snd_card_state(adev);
3464
3465 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3466 status = compress_pause(out->compr);
3467
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003468 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003469
Mingming Yin21854652016-04-13 11:54:02 -07003470 if (audio_extn_passthru_is_active()) {
3471 ALOGV("offload use case, pause passthru");
3472 audio_extn_passthru_on_pause(out);
3473 }
3474
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303475 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003476 audio_extn_dts_notify_playback_state(out->usecase, 0,
3477 out->sample_rate, popcount(out->channel_mask),
3478 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003479 }
3480 pthread_mutex_unlock(&out->lock);
3481 }
3482 return status;
3483}
3484
3485static int out_resume(struct audio_stream_out* stream)
3486{
3487 struct stream_out *out = (struct stream_out *)stream;
3488 int status = -ENOSYS;
3489 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003490 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003491 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003493 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003494 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303495 struct audio_device *adev = out->dev;
3496 int snd_scard_state = get_snd_card_state(adev);
3497
Mingming Yin21854652016-04-13 11:54:02 -07003498 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3499 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3500 pthread_mutex_lock(&out->dev->lock);
3501 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003502 pthread_mutex_unlock(&out->dev->lock);
3503 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303504 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003505 }
3506 if (!status) {
3507 out->offload_state = OFFLOAD_STATE_PLAYING;
3508 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303509 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003510 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3511 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 }
3513 pthread_mutex_unlock(&out->lock);
3514 }
3515 return status;
3516}
3517
3518static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3519{
3520 struct stream_out *out = (struct stream_out *)stream;
3521 int status = -ENOSYS;
3522 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003523 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003524 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3526 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3527 else
3528 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3529 pthread_mutex_unlock(&out->lock);
3530 }
3531 return status;
3532}
3533
3534static int out_flush(struct audio_stream_out* stream)
3535{
3536 struct stream_out *out = (struct stream_out *)stream;
3537 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003538 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003539 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003540 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003541 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3542 stop_compressed_output_l(out);
3543 out->written = 0;
3544 } else {
3545 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3546 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003547 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003548 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549 return 0;
3550 }
3551 return -ENOSYS;
3552}
3553
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554/** audio_stream_in implementation **/
3555static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3556{
3557 struct stream_in *in = (struct stream_in *)stream;
3558
3559 return in->config.rate;
3560}
3561
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003562static int in_set_sample_rate(struct audio_stream *stream __unused,
3563 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564{
3565 return -ENOSYS;
3566}
3567
3568static size_t in_get_buffer_size(const struct audio_stream *stream)
3569{
3570 struct stream_in *in = (struct stream_in *)stream;
3571
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003572 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3573 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003574 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3575 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303576 else if(audio_extn_cin_attached_usecase(in->usecase))
3577 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003578
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003579 return in->config.period_size * in->af_period_multiplier *
3580 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581}
3582
3583static uint32_t in_get_channels(const struct audio_stream *stream)
3584{
3585 struct stream_in *in = (struct stream_in *)stream;
3586
3587 return in->channel_mask;
3588}
3589
3590static audio_format_t in_get_format(const struct audio_stream *stream)
3591{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003592 struct stream_in *in = (struct stream_in *)stream;
3593
3594 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595}
3596
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003597static int in_set_format(struct audio_stream *stream __unused,
3598 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599{
3600 return -ENOSYS;
3601}
3602
3603static int in_standby(struct audio_stream *stream)
3604{
3605 struct stream_in *in = (struct stream_in *)stream;
3606 struct audio_device *adev = in->dev;
3607 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303608 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3609 stream, in->usecase, use_case_table[in->usecase]);
3610
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003611 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003612 if (!in->standby && in->is_st_session) {
3613 ALOGD("%s: sound trigger pcm stop lab", __func__);
3614 audio_extn_sound_trigger_stop_lab(in);
3615 in->standby = 1;
3616 }
3617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003618 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003619 if (adev->adm_deregister_stream)
3620 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3621
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003622 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003623 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003624 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3625 voice_extn_compress_voip_close_input_stream(stream);
3626 ALOGD("VOIP input entered standby");
3627 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303628 if (audio_extn_cin_attached_usecase(in->usecase))
3629 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003630 if (in->pcm) {
3631 pcm_close(in->pcm);
3632 in->pcm = NULL;
3633 }
3634 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003635 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003636 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637 }
3638 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003639 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 return status;
3641}
3642
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003643static int in_dump(const struct audio_stream *stream __unused,
3644 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645{
3646 return 0;
3647}
3648
3649static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3650{
3651 struct stream_in *in = (struct stream_in *)stream;
3652 struct audio_device *adev = in->dev;
3653 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003655 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303657 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 parms = str_parms_create_str(kvpairs);
3659
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303660 if (!parms)
3661 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003662 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003663 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003664
3665 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3666 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 val = atoi(value);
3668 /* no audio source uses val == 0 */
3669 if ((in->source != val) && (val != 0)) {
3670 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003671 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3672 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3673 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003674 (in->config.rate == 8000 || in->config.rate == 16000 ||
3675 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003676 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003677 err = voice_extn_compress_voip_open_input_stream(in);
3678 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003679 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003680 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003681 }
3682 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 }
3684 }
3685
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003686 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3687 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003689 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 in->device = val;
3691 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003692 if (!in->standby && !in->is_st_session) {
3693 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003694 if (adev->adm_on_routing_change)
3695 adev->adm_on_routing_change(adev->adm_data,
3696 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003697 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 }
3700 }
3701
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303702 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3703 if (err >= 0) {
3704 strlcpy(in->profile, value, sizeof(in->profile));
3705 ALOGV("updating stream profile with value '%s'", in->profile);
3706 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3707 &adev->streams_input_cfg_list,
3708 in->device, in->flags, in->format,
3709 in->sample_rate, in->bit_width,
3710 in->profile, &in->app_type_cfg);
3711 }
3712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003714 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715
3716 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303717error:
Eric Laurent994a6932013-07-17 11:51:42 -07003718 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 return ret;
3720}
3721
3722static char* in_get_parameters(const struct audio_stream *stream,
3723 const char *keys)
3724{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003725 struct stream_in *in = (struct stream_in *)stream;
3726 struct str_parms *query = str_parms_create_str(keys);
3727 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003728 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003729
3730 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003731 if (reply) {
3732 str_parms_destroy(reply);
3733 }
3734 if (query) {
3735 str_parms_destroy(query);
3736 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003737 ALOGE("in_get_parameters: failed to create query or reply");
3738 return NULL;
3739 }
3740
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003741 ALOGV("%s: enter: keys - %s", __func__, keys);
3742
3743 voice_extn_in_get_parameters(in, query, reply);
3744
3745 str = str_parms_to_str(reply);
3746 str_parms_destroy(query);
3747 str_parms_destroy(reply);
3748
3749 ALOGV("%s: exit: returns - %s", __func__, str);
3750 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751}
3752
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003753static int in_set_gain(struct audio_stream_in *stream __unused,
3754 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755{
3756 return 0;
3757}
3758
3759static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3760 size_t bytes)
3761{
3762 struct stream_in *in = (struct stream_in *)stream;
3763 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303764 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303765 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303766 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003768 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303769
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003770 if (in->is_st_session) {
3771 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3772 /* Read from sound trigger HAL */
3773 audio_extn_sound_trigger_read(in, buffer, bytes);
3774 pthread_mutex_unlock(&in->lock);
3775 return bytes;
3776 }
3777
Ashish Jainbbce4322016-02-16 13:25:27 +05303778 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003779 ALOGD(" %s: sound card is not active/SSR state", __func__);
3780 ret= -EIO;;
3781 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303782 }
3783
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003785 pthread_mutex_lock(&adev->lock);
3786 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3787 ret = voice_extn_compress_voip_start_input_stream(in);
3788 else
3789 ret = start_input_stream(in);
3790 pthread_mutex_unlock(&adev->lock);
3791 if (ret != 0) {
3792 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 }
3794 in->standby = 0;
3795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003797 // what's the duration requested by the client?
3798 long ns = 0;
3799
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303800 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003801 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3802 in->config.rate;
3803
3804 request_in_focus(in, ns);
3805 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003806
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303807 if (audio_extn_cin_attached_usecase(in->usecase)) {
3808 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3809 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303810 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003811 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303812 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003813 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003814 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003815 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303816 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003817 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303818 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3819 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3820 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3821 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303822 ret = -EINVAL;
3823 goto exit;
3824 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303825 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303826 ret = -errno;
3827 }
3828 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303829 /* bytes read is always set to bytes for non compress usecases */
3830 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831 }
3832
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003833 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 /*
3836 * Instead of writing zeroes here, we could trust the hardware
3837 * to always provide zeroes when muted.
3838 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303839 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3840 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 memset(buffer, 0, bytes);
3842
3843exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303844 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303845 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003846 if (-ENETRESET == ret)
3847 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 pthread_mutex_unlock(&in->lock);
3850
3851 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303852 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303853 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303854 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303855 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303856 in->standby = true;
3857 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303858 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3859 bytes_read = bytes;
3860 memset(buffer, 0, bytes);
3861 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003863 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303864 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303865 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303867 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868}
3869
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003870static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871{
3872 return 0;
3873}
3874
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003875static int add_remove_audio_effect(const struct audio_stream *stream,
3876 effect_handle_t effect,
3877 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003879 struct stream_in *in = (struct stream_in *)stream;
3880 int status = 0;
3881 effect_descriptor_t desc;
3882
3883 status = (*effect)->get_descriptor(effect, &desc);
3884 if (status != 0)
3885 return status;
3886
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003887 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003888 pthread_mutex_lock(&in->dev->lock);
3889 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3890 in->enable_aec != enable &&
3891 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3892 in->enable_aec = enable;
3893 if (!in->standby)
3894 select_devices(in->dev, in->usecase);
3895 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003896 if (in->enable_ns != enable &&
3897 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3898 in->enable_ns = enable;
3899 if (!in->standby)
3900 select_devices(in->dev, in->usecase);
3901 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003902 pthread_mutex_unlock(&in->dev->lock);
3903 pthread_mutex_unlock(&in->lock);
3904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905 return 0;
3906}
3907
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003908static int in_add_audio_effect(const struct audio_stream *stream,
3909 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910{
Eric Laurent994a6932013-07-17 11:51:42 -07003911 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003912 return add_remove_audio_effect(stream, effect, true);
3913}
3914
3915static int in_remove_audio_effect(const struct audio_stream *stream,
3916 effect_handle_t effect)
3917{
Eric Laurent994a6932013-07-17 11:51:42 -07003918 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003919 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920}
3921
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303922int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 audio_io_handle_t handle,
3924 audio_devices_t devices,
3925 audio_output_flags_t flags,
3926 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003927 struct audio_stream_out **stream_out,
3928 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003929{
3930 struct audio_device *adev = (struct audio_device *)dev;
3931 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303932 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003933 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003934 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303937
3938 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3939 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003940 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303941 return -EINVAL;
3942 }
3943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3945
Mingming Yin3a941d42016-02-17 18:08:05 -08003946 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3947 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303948 devices, flags, &out->stream);
3949
3950
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003951 if (!out) {
3952 return -ENOMEM;
3953 }
3954
Haynes Mathew George204045b2015-02-25 20:32:03 -08003955 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003956 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003957 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003959 if (devices == AUDIO_DEVICE_NONE)
3960 devices = AUDIO_DEVICE_OUT_SPEAKER;
3961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 out->flags = flags;
3963 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003964 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003965 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003966 out->sample_rate = config->sample_rate;
3967 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3968 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003969 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003970 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003971 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303972 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973
Mingming Yin3a941d42016-02-17 18:08:05 -08003974 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3975 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3976 pthread_mutex_lock(&adev->lock);
3977 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3978 ret = read_hdmi_sink_caps(out);
3979 pthread_mutex_unlock(&adev->lock);
3980 if (ret != 0) {
3981 if (ret == -ENOSYS) {
3982 /* ignore and go with default */
3983 ret = 0;
3984 } else {
3985 ALOGE("error reading hdmi sink caps");
3986 goto error_open;
3987 }
3988 }
3989 }
3990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303992 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003993 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003994 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003995 ret = voice_extn_compress_voip_open_output_stream(out);
3996 if (ret != 0) {
3997 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3998 __func__, ret);
3999 goto error_open;
4000 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004001 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304002 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004003
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004004 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4005 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4006 ALOGE("%s: Unsupported Offload information", __func__);
4007 ret = -EINVAL;
4008 goto error_open;
4009 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004010
Mingming Yin3a941d42016-02-17 18:08:05 -08004011 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004012 if(config->offload_info.format == 0)
4013 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004014 if (config->offload_info.sample_rate == 0)
4015 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004016 }
4017
Mingming Yin90310102013-11-13 16:57:00 -08004018 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304019 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004020 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004021 ret = -EINVAL;
4022 goto error_open;
4023 }
4024
4025 out->compr_config.codec = (struct snd_codec *)
4026 calloc(1, sizeof(struct snd_codec));
4027
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004028 if (!out->compr_config.codec) {
4029 ret = -ENOMEM;
4030 goto error_open;
4031 }
4032
Dhananjay Kumarac341582017-02-23 23:42:25 +05304033 out->stream.pause = out_pause;
4034 out->stream.resume = out_resume;
4035 out->stream.flush = out_flush;
4036 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004037 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004038 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304039 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004040 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304041 } else {
4042 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4043 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004044 }
vivek mehta446c3962015-09-14 10:57:35 -07004045
4046 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004047 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4048 config->format == 0 && config->sample_rate == 0 &&
4049 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004050 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004051 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4052 } else {
4053 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4054 ret = -EEXIST;
4055 goto error_open;
4056 }
vivek mehta446c3962015-09-14 10:57:35 -07004057 }
4058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004059 if (config->offload_info.channel_mask)
4060 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004061 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004062 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004063 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004064 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304065 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004066 ret = -EINVAL;
4067 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004068 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004069
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004070 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004071 out->sample_rate = config->offload_info.sample_rate;
4072
Mingming Yin3ee55c62014-08-04 14:23:35 -07004073 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004074
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304075 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4076 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4077 audio_extn_dolby_send_ddp_endp_params(adev);
4078 audio_extn_dolby_set_dmid(adev);
4079 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004080
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004081 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004082 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004083 out->compr_config.codec->bit_rate =
4084 config->offload_info.bit_rate;
4085 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304086 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004087 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304088 /* Update bit width only for non passthrough usecases.
4089 * For passthrough usecases, the output will always be opened @16 bit
4090 */
4091 if (!audio_extn_passthru_is_passthrough_stream(out))
4092 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004093 /*TODO: Do we need to change it for passthrough */
4094 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004095
Manish Dewangana6fc5442015-08-24 20:30:31 +05304096 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4097 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304098 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304099 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304100 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4101 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304102
4103 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4104 AUDIO_FORMAT_PCM) {
4105
4106 /*Based on platform support, configure appropriate alsa format for corresponding
4107 *hal input format.
4108 */
4109 out->compr_config.codec->format = hal_format_to_alsa(
4110 config->offload_info.format);
4111
Ashish Jain83a6cc22016-06-28 14:34:17 +05304112 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304113 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304114 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304115
Dhananjay Kumarac341582017-02-23 23:42:25 +05304116 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304117 *hal input format and alsa format might differ based on platform support.
4118 */
4119 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304120 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304121
4122 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4123
4124 /* Check if alsa session is configured with the same format as HAL input format,
4125 * if not then derive correct fragment size needed to accomodate the
4126 * conversion of HAL input format to alsa format.
4127 */
4128 audio_extn_utils_update_direct_pcm_fragment_size(out);
4129
4130 /*if hal input and output fragment size is different this indicates HAL input format is
4131 *not same as the alsa format
4132 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304133 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304134 /*Allocate a buffer to convert input data to the alsa configured format.
4135 *size of convert buffer is equal to the size required to hold one fragment size
4136 *worth of pcm data, this is because flinger does not write more than fragment_size
4137 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304138 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4139 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304140 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4141 ret = -ENOMEM;
4142 goto error_open;
4143 }
4144 }
4145 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4146 out->compr_config.fragment_size =
4147 audio_extn_passthru_get_buffer_size(&config->offload_info);
4148 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4149 } else {
4150 out->compr_config.fragment_size =
4151 platform_get_compress_offload_buffer_size(&config->offload_info);
4152 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4153 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004154
Amit Shekhar6f461b12014-08-01 14:52:58 -07004155 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304156 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004157
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304158 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4159 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4160 }
4161
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004162 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4163 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004164
Manish Dewangan69426c82017-01-30 17:35:36 +05304165 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4166 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4167 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4168 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4169 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4170 } else {
4171 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4172 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004173
Manish Dewangan27346042017-03-01 12:56:12 +05304174 memset(&out->render_window, 0,
4175 sizeof(struct audio_out_render_window_param));
4176
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004177 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304178 out->send_next_track_params = false;
4179 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004180 out->offload_state = OFFLOAD_STATE_IDLE;
4181 out->playback_started = 0;
4182
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004183 audio_extn_dts_create_state_notifier_node(out->usecase);
4184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004185 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4186 __func__, config->offload_info.version,
4187 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304188
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304189 /* Check if DSD audio format is supported in codec
4190 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304191 */
4192
4193 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304194 (!platform_check_codec_dsd_support(adev->platform) ||
4195 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304196 ret = -EINVAL;
4197 goto error_open;
4198 }
4199
Ashish Jain5106d362016-05-11 19:23:33 +05304200 /* Disable gapless if any of the following is true
4201 * passthrough playback
4202 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304203 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304204 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304205 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304206 (config->format == AUDIO_FORMAT_DSD) ||
4207 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304208 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304209 check_and_set_gapless_mode(adev, false);
4210 } else
4211 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004212
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304213 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004214 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4215 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304216 if (config->format == AUDIO_FORMAT_DSD) {
4217 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4218 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4219 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004220
4221 create_offload_callback_thread(out);
4222
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004223 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304224 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004225 if (ret != 0) {
4226 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4227 __func__, ret);
4228 goto error_open;
4229 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004230 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4231 if (config->sample_rate == 0)
4232 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4233 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4234 config->sample_rate != 8000) {
4235 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4236 ret = -EINVAL;
4237 goto error_open;
4238 }
4239 out->sample_rate = config->sample_rate;
4240 out->config.rate = config->sample_rate;
4241 if (config->format == AUDIO_FORMAT_DEFAULT)
4242 config->format = AUDIO_FORMAT_PCM_16_BIT;
4243 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4244 config->format = AUDIO_FORMAT_PCM_16_BIT;
4245 ret = -EINVAL;
4246 goto error_open;
4247 }
4248 out->format = config->format;
4249 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4250 out->config = pcm_config_afe_proxy_playback;
4251 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004252 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304253 unsigned int channels = 0;
4254 /*Update config params to default if not set by the caller*/
4255 if (config->sample_rate == 0)
4256 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4257 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4258 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4259 if (config->format == AUDIO_FORMAT_DEFAULT)
4260 config->format = AUDIO_FORMAT_PCM_16_BIT;
4261
4262 channels = audio_channel_count_from_out_mask(out->channel_mask);
4263
Ashish Jain83a6cc22016-06-28 14:34:17 +05304264 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4265 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004266 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4267 out->flags);
4268 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304269 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4270 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4271 out->config = pcm_config_low_latency;
4272 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4273 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4274 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304275 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4276 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4277 if (out->config.period_size <= 0) {
4278 ALOGE("Invalid configuration period size is not valid");
4279 ret = -EINVAL;
4280 goto error_open;
4281 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304282 } else {
4283 /* primary path is the default path selected if no other outputs are available/suitable */
4284 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4285 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4286 }
4287 out->hal_ip_format = format = out->format;
4288 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4289 out->hal_op_format = pcm_format_to_hal(out->config.format);
4290 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4291 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004292 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304293 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304294 if (out->hal_ip_format != out->hal_op_format) {
4295 uint32_t buffer_size = out->config.period_size *
4296 format_to_bitwidth_table[out->hal_op_format] *
4297 out->config.channels;
4298 out->convert_buffer = calloc(1, buffer_size);
4299 if (out->convert_buffer == NULL){
4300 ALOGE("Allocation failed for convert buffer for size %d",
4301 out->compr_config.fragment_size);
4302 ret = -ENOMEM;
4303 goto error_open;
4304 }
4305 ALOGD("Convert buffer allocated of size %d", buffer_size);
4306 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004307 }
4308
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004309 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4310 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304311
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004312 /* TODO remove this hardcoding and check why width is zero*/
4313 if (out->bit_width == 0)
4314 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304315 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004316 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304317 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304318 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304319 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004320 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4321 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4322 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004323 if(adev->primary_output == NULL)
4324 adev->primary_output = out;
4325 else {
4326 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004327 ret = -EEXIST;
4328 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004329 }
4330 }
4331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332 /* Check if this usecase is already existing */
4333 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004334 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4335 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004338 ret = -EEXIST;
4339 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342 pthread_mutex_unlock(&adev->lock);
4343
4344 out->stream.common.get_sample_rate = out_get_sample_rate;
4345 out->stream.common.set_sample_rate = out_set_sample_rate;
4346 out->stream.common.get_buffer_size = out_get_buffer_size;
4347 out->stream.common.get_channels = out_get_channels;
4348 out->stream.common.get_format = out_get_format;
4349 out->stream.common.set_format = out_set_format;
4350 out->stream.common.standby = out_standby;
4351 out->stream.common.dump = out_dump;
4352 out->stream.common.set_parameters = out_set_parameters;
4353 out->stream.common.get_parameters = out_get_parameters;
4354 out->stream.common.add_audio_effect = out_add_audio_effect;
4355 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4356 out->stream.get_latency = out_get_latency;
4357 out->stream.set_volume = out_set_volume;
4358 out->stream.write = out_write;
4359 out->stream.get_render_position = out_get_render_position;
4360 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004361 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004363 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004365 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004366 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367
4368 config->format = out->stream.common.get_format(&out->stream.common);
4369 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4370 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4371
4372 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304373 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004374 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004375
4376 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4377 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4378 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004379 /* setup a channel for client <--> adsp communication for stream events */
4380 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
4381 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
4382 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4383 out->usecase, PCM_PLAYBACK);
4384 hdlr_stream_cfg.flags = out->flags;
4385 hdlr_stream_cfg.type = PCM_PLAYBACK;
4386 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4387 &hdlr_stream_cfg);
4388 if (ret) {
4389 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4390 out->adsp_hdlr_stream_handle = NULL;
4391 }
4392 }
Eric Laurent994a6932013-07-17 11:51:42 -07004393 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004395
4396error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304397 if (out->convert_buffer)
4398 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004399 free(out);
4400 *stream_out = NULL;
4401 ALOGD("%s: exit: ret %d", __func__, ret);
4402 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403}
4404
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304405void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406 struct audio_stream_out *stream)
4407{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004408 struct stream_out *out = (struct stream_out *)stream;
4409 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004410 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004411
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304412 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4413
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004414 /* close adsp hdrl session before standby */
4415 if (out->adsp_hdlr_stream_handle) {
4416 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4417 if (ret)
4418 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4419 out->adsp_hdlr_stream_handle = NULL;
4420 }
4421
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004422 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304423 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004424 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304425 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004426 if(ret != 0)
4427 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4428 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004429 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004430 out_standby(&stream->common);
4431
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004432 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004433 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004434 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004435 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004436 if (out->compr_config.codec != NULL)
4437 free(out->compr_config.codec);
4438 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004439
Ashish Jain83a6cc22016-06-28 14:34:17 +05304440 if (out->convert_buffer != NULL) {
4441 free(out->convert_buffer);
4442 out->convert_buffer = NULL;
4443 }
4444
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004445 if (adev->voice_tx_output == out)
4446 adev->voice_tx_output = NULL;
4447
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304448 if (adev->primary_output == out)
4449 adev->primary_output = NULL;
4450
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004451 pthread_cond_destroy(&out->cond);
4452 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004453 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004454 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455}
4456
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004457static void close_compress_sessions(struct audio_device *adev)
4458{
Mingming Yin7b762e72015-03-04 13:47:32 -08004459 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304460 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004461 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004462 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304463
4464 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004465 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304466 if (is_offload_usecase(usecase->id)) {
4467 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004468 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4469 out = usecase->stream.out;
4470 pthread_mutex_unlock(&adev->lock);
4471 out_standby(&out->stream.common);
4472 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004473 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004474 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304475 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004476 }
4477 pthread_mutex_unlock(&adev->lock);
4478}
4479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4481{
4482 struct audio_device *adev = (struct audio_device *)dev;
4483 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004485 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004486 int ret;
4487 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004488
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004489 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004491
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304492 if (!parms)
4493 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004494 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4495 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304496 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304497 if (strstr(snd_card_status, "OFFLINE")) {
4498 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304499 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004500 //close compress sessions on OFFLINE status
4501 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304502 } else if (strstr(snd_card_status, "ONLINE")) {
4503 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304504 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004505 //send dts hpx license if enabled
4506 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304507 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304508 }
4509
4510 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004511 status = voice_set_parameters(adev, parms);
4512 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004513 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004515 status = platform_set_parameters(adev->platform, parms);
4516 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004517 goto done;
4518
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004519 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4520 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004521 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4523 adev->bluetooth_nrec = true;
4524 else
4525 adev->bluetooth_nrec = false;
4526 }
4527
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004528 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4529 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4531 adev->screen_off = false;
4532 else
4533 adev->screen_off = true;
4534 }
4535
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004536 ret = str_parms_get_int(parms, "rotation", &val);
4537 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004538 bool reverse_speakers = false;
4539 switch(val) {
4540 // FIXME: note that the code below assumes that the speakers are in the correct placement
4541 // relative to the user when the device is rotated 90deg from its default rotation. This
4542 // assumption is device-specific, not platform-specific like this code.
4543 case 270:
4544 reverse_speakers = true;
4545 break;
4546 case 0:
4547 case 90:
4548 case 180:
4549 break;
4550 default:
4551 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004552 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004553 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004554 if (status == 0) {
4555 if (adev->speaker_lr_swap != reverse_speakers) {
4556 adev->speaker_lr_swap = reverse_speakers;
4557 // only update the selected device if there is active pcm playback
4558 struct audio_usecase *usecase;
4559 struct listnode *node;
4560 list_for_each(node, &adev->usecase_list) {
4561 usecase = node_to_item(node, struct audio_usecase, list);
4562 if (usecase->type == PCM_PLAYBACK) {
4563 select_devices(adev, usecase->id);
4564 break;
4565 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004566 }
4567 }
4568 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004569 }
4570
Mingming Yin514a8bc2014-07-29 15:22:21 -07004571 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4572 if (ret >= 0) {
4573 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4574 adev->bt_wb_speech_enabled = true;
4575 else
4576 adev->bt_wb_speech_enabled = false;
4577 }
4578
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004579 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4580 if (ret >= 0) {
4581 val = atoi(value);
4582 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004583 ALOGV("cache new ext disp type and edid");
4584 ret = platform_get_ext_disp_type(adev->platform);
4585 if (ret < 0) {
4586 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004587 status = ret;
4588 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004589 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004590 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004591 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004592 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004593 /*
4594 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4595 * Per AudioPolicyManager, USB device is higher priority than WFD.
4596 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4597 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4598 * starting voice call on USB
4599 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004600 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4601 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004602 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4603 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004604 }
vivek mehta344576a2016-04-12 18:56:03 -07004605 ALOGV("detected USB connect .. disable proxy");
4606 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004607 }
4608 }
4609
4610 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4611 if (ret >= 0) {
4612 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004613 /*
4614 * The HDMI / Displayport disconnect handling has been moved to
4615 * audio extension to ensure that its parameters are not
4616 * invalidated prior to updating sysfs of the disconnect event
4617 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4618 */
4619 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004620 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004621 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4622 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304623 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4624 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004625 }
vivek mehta344576a2016-04-12 18:56:03 -07004626 ALOGV("detected USB disconnect .. enable proxy");
4627 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004628 }
4629 }
4630
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304631 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4632 if (ret >= 0) {
4633 struct audio_usecase *usecase;
4634 struct listnode *node;
4635 list_for_each(node, &adev->usecase_list) {
4636 usecase = node_to_item(node, struct audio_usecase, list);
4637 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004638 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304639 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304640 lock_output_stream(usecase->stream.out);
4641 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304642 //force device switch to re configure encoder
4643 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304644 audio_extn_a2dp_set_handoff_mode(false);
4645 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304646 break;
4647 }
4648 }
4649 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004650
4651 //handle vr audio setparam
4652 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4653 value, sizeof(value));
4654 if (ret >= 0) {
4655 ALOGI("Setting vr mode to be %s", value);
4656 if (!strncmp(value, "true", 4)) {
4657 adev->vr_audio_mode_enabled = true;
4658 ALOGI("Setting vr mode to true");
4659 } else if (!strncmp(value, "false", 5)) {
4660 adev->vr_audio_mode_enabled = false;
4661 ALOGI("Setting vr mode to false");
4662 } else {
4663 ALOGI("wrong vr mode set");
4664 }
4665 }
4666
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304667 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004668done:
4669 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004670 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304671error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004672 ALOGV("%s: exit with code(%d)", __func__, status);
4673 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674}
4675
4676static char* adev_get_parameters(const struct audio_hw_device *dev,
4677 const char *keys)
4678{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004679 struct audio_device *adev = (struct audio_device *)dev;
4680 struct str_parms *reply = str_parms_create();
4681 struct str_parms *query = str_parms_create_str(keys);
4682 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304683 char value[256] = {0};
4684 int ret = 0;
4685
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004686 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004687 if (reply) {
4688 str_parms_destroy(reply);
4689 }
4690 if (query) {
4691 str_parms_destroy(query);
4692 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004693 ALOGE("adev_get_parameters: failed to create query or reply");
4694 return NULL;
4695 }
4696
Naresh Tannirud7205b62014-06-20 02:54:48 +05304697 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4698 sizeof(value));
4699 if (ret >=0) {
4700 int val = 1;
4701 pthread_mutex_lock(&adev->snd_card_status.lock);
4702 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4703 val = 0;
4704 pthread_mutex_unlock(&adev->snd_card_status.lock);
4705 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4706 goto exit;
4707 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004708 //handle vr audio getparam
4709
4710 ret = str_parms_get_str(query,
4711 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4712 value, sizeof(value));
4713
4714 if (ret >= 0) {
4715 bool vr_audio_enabled = false;
4716 pthread_mutex_lock(&adev->lock);
4717 vr_audio_enabled = adev->vr_audio_mode_enabled;
4718 pthread_mutex_unlock(&adev->lock);
4719
4720 ALOGI("getting vr mode to %d", vr_audio_enabled);
4721
4722 if (vr_audio_enabled) {
4723 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4724 "true");
4725 goto exit;
4726 } else {
4727 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4728 "false");
4729 goto exit;
4730 }
4731 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004732
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004733 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004734 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004735 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004736 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304737 pthread_mutex_unlock(&adev->lock);
4738
Naresh Tannirud7205b62014-06-20 02:54:48 +05304739exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004740 str = str_parms_to_str(reply);
4741 str_parms_destroy(query);
4742 str_parms_destroy(reply);
4743
4744 ALOGV("%s: exit: returns - %s", __func__, str);
4745 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746}
4747
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004748static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004749{
4750 return 0;
4751}
4752
4753static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4754{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004755 int ret;
4756 struct audio_device *adev = (struct audio_device *)dev;
4757 pthread_mutex_lock(&adev->lock);
4758 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004759 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004760 pthread_mutex_unlock(&adev->lock);
4761 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762}
4763
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004764static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4765 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766{
4767 return -ENOSYS;
4768}
4769
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004770static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4771 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772{
4773 return -ENOSYS;
4774}
4775
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004776static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4777 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778{
4779 return -ENOSYS;
4780}
4781
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004782static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4783 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784{
4785 return -ENOSYS;
4786}
4787
4788static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4789{
4790 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004792 pthread_mutex_lock(&adev->lock);
4793 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004794 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004796 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004797 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004798 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004799 adev->current_call_output = NULL;
4800 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801 }
4802 pthread_mutex_unlock(&adev->lock);
4803 return 0;
4804}
4805
4806static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4807{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004808 int ret;
4809
4810 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004811 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004812 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4813 pthread_mutex_unlock(&adev->lock);
4814
4815 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004816}
4817
4818static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4819{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004820 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821 return 0;
4822}
4823
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004824static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004825 const struct audio_config *config)
4826{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004827 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004829 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4830 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831}
4832
4833static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004834 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004835 audio_devices_t devices,
4836 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004837 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304838 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004839 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004840 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841{
4842 struct audio_device *adev = (struct audio_device *)dev;
4843 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004844 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004845 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004846 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304847 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304850 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4851 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304853 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854
4855 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004856
4857 if (!in) {
4858 ALOGE("failed to allocate input stream");
4859 return -ENOMEM;
4860 }
4861
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304862 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304863 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4864 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004865 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004866 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868 in->stream.common.get_sample_rate = in_get_sample_rate;
4869 in->stream.common.set_sample_rate = in_set_sample_rate;
4870 in->stream.common.get_buffer_size = in_get_buffer_size;
4871 in->stream.common.get_channels = in_get_channels;
4872 in->stream.common.get_format = in_get_format;
4873 in->stream.common.set_format = in_set_format;
4874 in->stream.common.standby = in_standby;
4875 in->stream.common.dump = in_dump;
4876 in->stream.common.set_parameters = in_set_parameters;
4877 in->stream.common.get_parameters = in_get_parameters;
4878 in->stream.common.add_audio_effect = in_add_audio_effect;
4879 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4880 in->stream.set_gain = in_set_gain;
4881 in->stream.read = in_read;
4882 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4883
4884 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004885 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887 in->standby = 1;
4888 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004889 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004890 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304892 in->usecase = USECASE_AUDIO_RECORD;
4893 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4894 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4895 is_low_latency = true;
4896#if LOW_LATENCY_CAPTURE_USE_CASE
4897 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4898#endif
4899 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4900 }
4901
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004902 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004903 if (in->realtime) {
4904 in->config = pcm_config_audio_capture_rt;
4905 in->sample_rate = in->config.rate;
4906 in->af_period_multiplier = af_period_multiplier;
4907 } else {
4908 in->config = pcm_config_audio_capture;
4909 in->config.rate = config->sample_rate;
4910 in->sample_rate = config->sample_rate;
4911 in->af_period_multiplier = 1;
4912 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304913 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004914
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304915 /* restrict 24 bit capture for unprocessed source only
4916 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4917 */
4918 if (config->format == AUDIO_FORMAT_DEFAULT) {
4919 config->format = AUDIO_FORMAT_PCM_16_BIT;
4920 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4921 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4922 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4923 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4924 bool ret_error = false;
4925 in->bit_width = 24;
4926 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4927 from HAL is 24_packed and 8_24
4928 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4929 24_packed return error indicating supported format is 24_packed
4930 *> In case of any other source requesting 24 bit or float return error
4931 indicating format supported is 16 bit only.
4932
4933 on error flinger will retry with supported format passed
4934 */
4935 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4936 (source != AUDIO_SOURCE_CAMCORDER)) {
4937 config->format = AUDIO_FORMAT_PCM_16_BIT;
4938 if (config->sample_rate > 48000)
4939 config->sample_rate = 48000;
4940 ret_error = true;
4941 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4942 in->config.format = PCM_FORMAT_S24_3LE;
4943 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4944 in->config.format = PCM_FORMAT_S24_LE;
4945 } else {
4946 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4947 ret_error = true;
4948 }
4949
4950 if (ret_error) {
4951 ret = -EINVAL;
4952 goto err_open;
4953 }
4954 }
4955
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304956 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304957 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4958 (adev->mode != AUDIO_MODE_IN_CALL)) {
4959 ret = -EINVAL;
4960 goto err_open;
4961 }
4962
4963 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4964 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004965 if (config->sample_rate == 0)
4966 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4967 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4968 config->sample_rate != 8000) {
4969 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4970 ret = -EINVAL;
4971 goto err_open;
4972 }
4973 if (config->format == AUDIO_FORMAT_DEFAULT)
4974 config->format = AUDIO_FORMAT_PCM_16_BIT;
4975 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4976 config->format = AUDIO_FORMAT_PCM_16_BIT;
4977 ret = -EINVAL;
4978 goto err_open;
4979 }
4980
4981 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4982 in->config = pcm_config_afe_proxy_record;
4983 in->config.channels = channel_count;
4984 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304985 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304986 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4987 in, config, &channel_mask_updated)) {
4988 if (channel_mask_updated == true) {
4989 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4990 __func__, config->channel_mask);
4991 ret = -EINVAL;
4992 goto err_open;
4993 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304994 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004995 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004996 audio_extn_compr_cap_format_supported(config->format) &&
4997 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004998 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304999 } else if (audio_extn_cin_applicable_stream(in)) {
5000 ret = audio_extn_cin_configure_input_stream(in);
5001 if (ret)
5002 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005003 } else {
5004 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005005 if (!in->realtime) {
5006 in->format = config->format;
5007 frame_size = audio_stream_in_frame_size(&in->stream);
5008 buffer_size = get_input_buffer_size(config->sample_rate,
5009 config->format,
5010 channel_count,
5011 is_low_latency);
5012 in->config.period_size = buffer_size / frame_size;
5013 }
5014
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005015 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005016 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005017 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005018 (in->config.rate == 8000 || in->config.rate == 16000 ||
5019 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005020 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5021 voice_extn_compress_voip_open_input_stream(in);
5022 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005023 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005024
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305025 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5026 &adev->streams_input_cfg_list,
5027 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305028 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305029
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005030 /* This stream could be for sound trigger lab,
5031 get sound trigger pcm if present */
5032 audio_extn_sound_trigger_check_and_get_session(in);
5033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005034 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005035 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005036 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037
5038err_open:
5039 free(in);
5040 *stream_in = NULL;
5041 return ret;
5042}
5043
5044static void adev_close_input_stream(struct audio_hw_device *dev,
5045 struct audio_stream_in *stream)
5046{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005047 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005048 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005049 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305050
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305051 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005052
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305053 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005054 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305055
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005056 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305057 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005058 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305059 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005060 if (ret != 0)
5061 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5062 __func__, ret);
5063 } else
5064 in_standby(&stream->common);
5065
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005066 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005067 audio_extn_ssr_deinit();
5068 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005069
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305070 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005071 audio_extn_compr_cap_format_supported(in->config.format))
5072 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305073
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305074 if (audio_extn_cin_attached_usecase(in->usecase))
5075 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005076
Mingming Yinfd7607b2016-01-22 12:48:44 -08005077 if (in->is_st_session) {
5078 ALOGV("%s: sound trigger pcm stop lab", __func__);
5079 audio_extn_sound_trigger_stop_lab(in);
5080 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005081 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082 return;
5083}
5084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005085static int adev_dump(const audio_hw_device_t *device __unused,
5086 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087{
5088 return 0;
5089}
5090
5091static int adev_close(hw_device_t *device)
5092{
5093 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005094
5095 if (!adev)
5096 return 0;
5097
5098 pthread_mutex_lock(&adev_init_lock);
5099
5100 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005101 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005102 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305103 audio_extn_utils_release_streams_cfg_lists(
5104 &adev->streams_output_cfg_list,
5105 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305106 if (audio_extn_qaf_is_enabled())
5107 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005108 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005109 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005110 free(adev->snd_dev_ref_cnt);
5111 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005112 if (adev->adm_deinit)
5113 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305114 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005115 audio_extn_adsp_hdlr_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005116 free(device);
5117 adev = NULL;
5118 }
5119 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 return 0;
5122}
5123
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005124/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5125 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5126 * just that it _might_ work.
5127 */
5128static int period_size_is_plausible_for_low_latency(int period_size)
5129{
5130 switch (period_size) {
5131 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005132 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005133 case 240:
5134 case 320:
5135 case 480:
5136 return 1;
5137 default:
5138 return 0;
5139 }
5140}
5141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142static int adev_open(const hw_module_t *module, const char *name,
5143 hw_device_t **device)
5144{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305145 int ret;
5146
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005147 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005148 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5149
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005150 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005151 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005152 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005153 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005154 ALOGD("%s: returning existing instance of adev", __func__);
5155 ALOGD("%s: exit", __func__);
5156 pthread_mutex_unlock(&adev_init_lock);
5157 return 0;
5158 }
5159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160 adev = calloc(1, sizeof(struct audio_device));
5161
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005162 if (!adev) {
5163 pthread_mutex_unlock(&adev_init_lock);
5164 return -ENOMEM;
5165 }
5166
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005167 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005169 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5170 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5171 adev->device.common.module = (struct hw_module_t *)module;
5172 adev->device.common.close = adev_close;
5173
5174 adev->device.init_check = adev_init_check;
5175 adev->device.set_voice_volume = adev_set_voice_volume;
5176 adev->device.set_master_volume = adev_set_master_volume;
5177 adev->device.get_master_volume = adev_get_master_volume;
5178 adev->device.set_master_mute = adev_set_master_mute;
5179 adev->device.get_master_mute = adev_get_master_mute;
5180 adev->device.set_mode = adev_set_mode;
5181 adev->device.set_mic_mute = adev_set_mic_mute;
5182 adev->device.get_mic_mute = adev_get_mic_mute;
5183 adev->device.set_parameters = adev_set_parameters;
5184 adev->device.get_parameters = adev_get_parameters;
5185 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5186 adev->device.open_output_stream = adev_open_output_stream;
5187 adev->device.close_output_stream = adev_close_output_stream;
5188 adev->device.open_input_stream = adev_open_input_stream;
5189 adev->device.close_input_stream = adev_close_input_stream;
5190 adev->device.dump = adev_dump;
5191
5192 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005193 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005194 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005195 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005196 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005198 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005199 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005200 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005201 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005202 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005203 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005204 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005205 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305206 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305207 adev->perf_lock_opts[0] = 0x101;
5208 adev->perf_lock_opts[1] = 0x20E;
5209 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305210
5211 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5212 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005214 adev->platform = platform_init(adev);
5215 if (!adev->platform) {
5216 free(adev->snd_dev_ref_cnt);
5217 free(adev);
5218 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5219 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005220 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305221 pthread_mutex_destroy(&adev->lock);
5222 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005223 return -EINVAL;
5224 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005225
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305226 if (audio_extn_qaf_is_enabled()) {
5227 ret = audio_extn_qaf_init(adev);
5228 if (ret < 0) {
5229 free(adev);
5230 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5231 *device = NULL;
5232 pthread_mutex_unlock(&adev_init_lock);
5233 pthread_mutex_destroy(&adev->lock);
5234 return ret;
5235 }
5236
5237 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5238 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5239 }
5240
Naresh Tanniru4c630392014-05-12 01:05:52 +05305241 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5242
Eric Laurentc4aef752013-09-12 17:45:53 -07005243 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5244 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5245 if (adev->visualizer_lib == NULL) {
5246 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5247 } else {
5248 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5249 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005250 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005251 "visualizer_hal_start_output");
5252 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005253 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005254 "visualizer_hal_stop_output");
5255 }
5256 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305257 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005258 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005259 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005260 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005261
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005262 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5263 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5264 if (adev->offload_effects_lib == NULL) {
5265 ALOGE("%s: DLOPEN failed for %s", __func__,
5266 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5267 } else {
5268 ALOGV("%s: DLOPEN successful for %s", __func__,
5269 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5270 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305271 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005272 "offload_effects_bundle_hal_start_output");
5273 adev->offload_effects_stop_output =
5274 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5275 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005276 adev->offload_effects_set_hpx_state =
5277 (int (*)(bool))dlsym(adev->offload_effects_lib,
5278 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305279 adev->offload_effects_get_parameters =
5280 (void (*)(struct str_parms *, struct str_parms *))
5281 dlsym(adev->offload_effects_lib,
5282 "offload_effects_bundle_get_parameters");
5283 adev->offload_effects_set_parameters =
5284 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5285 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005286 }
5287 }
5288
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005289 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5290 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5291 if (adev->adm_lib == NULL) {
5292 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5293 } else {
5294 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5295 adev->adm_init = (adm_init_t)
5296 dlsym(adev->adm_lib, "adm_init");
5297 adev->adm_deinit = (adm_deinit_t)
5298 dlsym(adev->adm_lib, "adm_deinit");
5299 adev->adm_register_input_stream = (adm_register_input_stream_t)
5300 dlsym(adev->adm_lib, "adm_register_input_stream");
5301 adev->adm_register_output_stream = (adm_register_output_stream_t)
5302 dlsym(adev->adm_lib, "adm_register_output_stream");
5303 adev->adm_deregister_stream = (adm_deregister_stream_t)
5304 dlsym(adev->adm_lib, "adm_deregister_stream");
5305 adev->adm_request_focus = (adm_request_focus_t)
5306 dlsym(adev->adm_lib, "adm_request_focus");
5307 adev->adm_abandon_focus = (adm_abandon_focus_t)
5308 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005309 adev->adm_set_config = (adm_set_config_t)
5310 dlsym(adev->adm_lib, "adm_set_config");
5311 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5312 dlsym(adev->adm_lib, "adm_request_focus_v2");
5313 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5314 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5315 adev->adm_on_routing_change = (adm_on_routing_change_t)
5316 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005317 }
5318 }
5319
Mingming Yin514a8bc2014-07-29 15:22:21 -07005320 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005321 //initialize this to false for now,
5322 //this will be set to true through set param
5323 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005324
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005325 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005326 *device = &adev->device.common;
5327
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305328 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5329 &adev->streams_output_cfg_list,
5330 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005331
Kiran Kandi910e1862013-10-29 13:29:42 -07005332 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005333
5334 char value[PROPERTY_VALUE_MAX];
5335 int trial;
5336 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5337 trial = atoi(value);
5338 if (period_size_is_plausible_for_low_latency(trial)) {
5339 pcm_config_low_latency.period_size = trial;
5340 pcm_config_low_latency.start_threshold = trial / 4;
5341 pcm_config_low_latency.avail_min = trial / 4;
5342 configured_low_latency_capture_period_size = trial;
5343 }
5344 }
5345 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5346 trial = atoi(value);
5347 if (period_size_is_plausible_for_low_latency(trial)) {
5348 configured_low_latency_capture_period_size = trial;
5349 }
5350 }
5351
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005352 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5353 af_period_multiplier = atoi(value);
5354 if (af_period_multiplier < 0)
5355 af_period_multiplier = 2;
5356 else if (af_period_multiplier > 4)
5357 af_period_multiplier = 4;
5358
5359 ALOGV("new period_multiplier = %d", af_period_multiplier);
5360 }
5361
vivek mehta446c3962015-09-14 10:57:35 -07005362 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005363 pthread_mutex_unlock(&adev_init_lock);
5364
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005365 if (adev->adm_init)
5366 adev->adm_data = adev->adm_init();
5367
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305368 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305369 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005370 audio_extn_adsp_hdlr_init(adev->mixer);
Eric Laurent994a6932013-07-17 11:51:42 -07005371 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005372 return 0;
5373}
5374
5375static struct hw_module_methods_t hal_module_methods = {
5376 .open = adev_open,
5377};
5378
5379struct audio_module HAL_MODULE_INFO_SYM = {
5380 .common = {
5381 .tag = HARDWARE_MODULE_TAG,
5382 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5383 .hal_api_version = HARDWARE_HAL_API_VERSION,
5384 .id = AUDIO_HARDWARE_MODULE_ID,
5385 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005386 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005387 .methods = &hal_module_methods,
5388 },
5389};