blob: 5b320d78f62490fab945bf47a28e1844000331f6 [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);
yidongh6261d8e2017-05-15 17:04:02 +08001531 if ((voip_usecase != NULL) &&
1532 (usecase->type == PCM_PLAYBACK) &&
1533 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001534 out_snd_device_backend_match = platform_check_backends_match(
1535 voip_usecase->out_snd_device,
1536 platform_get_output_snd_device(
1537 adev->platform,
1538 usecase->stream.out));
1539 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001540 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001541 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1542 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001543 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001544 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001545 in_snd_device = voip_usecase->in_snd_device;
1546 out_snd_device = voip_usecase->out_snd_device;
1547 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001548 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001549 hfp_ucid = audio_extn_hfp_get_usecase();
1550 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001551 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001552 in_snd_device = hfp_usecase->in_snd_device;
1553 out_snd_device = hfp_usecase->out_snd_device;
1554 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001555 }
1556 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301557 if (usecase->stream.out == NULL) {
1558 ALOGE("%s: stream.out is NULL", __func__);
1559 return -EINVAL;
1560 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561 usecase->devices = usecase->stream.out->devices;
1562 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001563 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001564 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001565 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001566 if (usecase->stream.out == adev->primary_output &&
1567 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001568 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001569 select_devices(adev, adev->active_input->usecase);
1570 }
1571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301573 if (usecase->stream.in == NULL) {
1574 ALOGE("%s: stream.in is NULL", __func__);
1575 return -EINVAL;
1576 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 usecase->devices = usecase->stream.in->device;
1578 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001579 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001580 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001581 if (adev->active_input &&
1582 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301583 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1584 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1585 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001586 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001587 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001588 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1589 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001590 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001591 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001592 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001593 }
1594 }
1595
1596 if (out_snd_device == usecase->out_snd_device &&
1597 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301598
1599 if (!force_device_switch(usecase))
1600 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001601 }
1602
sangwoobc677242013-08-08 16:53:43 +09001603 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001604 out_snd_device, platform_get_snd_device_name(out_snd_device),
1605 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607 /*
1608 * Limitation: While in call, to do a device switch we need to disable
1609 * and enable both RX and TX devices though one of them is same as current
1610 * device.
1611 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001612 if ((usecase->type == VOICE_CALL) &&
1613 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1614 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001615 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001616 }
1617
1618 if (((usecase->type == VOICE_CALL) ||
1619 (usecase->type == VOIP_CALL)) &&
1620 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1621 /* Disable sidetone only if voice/voip call already exists */
1622 if (voice_is_call_state_active(adev) ||
1623 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001624 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001625
1626 /* Disable aanc only if voice call exists */
1627 if (voice_is_call_state_active(adev))
1628 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001629 }
1630
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001631 /* Disable current sound devices */
1632 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001633 disable_audio_route(adev, usecase);
1634 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635 }
1636
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001637 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001638 disable_audio_route(adev, usecase);
1639 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640 }
1641
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001642 /* Applicable only on the targets that has external modem.
1643 * New device information should be sent to modem before enabling
1644 * the devices to reduce in-call device switch time.
1645 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001646 if ((usecase->type == VOICE_CALL) &&
1647 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1648 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001649 status = platform_switch_voice_call_enable_device_config(adev->platform,
1650 out_snd_device,
1651 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001652 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001653
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001654 /* Enable new sound devices */
1655 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001656 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301657 if (platform_check_codec_asrc_support(adev->platform))
1658 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001659 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 }
1661
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001662 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301663 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001664 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001665 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001666
Avinash Vaish71a8b972014-07-24 15:36:33 +05301667 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001668 status = platform_switch_voice_call_device_post(adev->platform,
1669 out_snd_device,
1670 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301671 enable_audio_route_for_voice_usecases(adev, usecase);
1672 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001673
sangwoo170731f2013-06-08 15:36:36 +09001674 usecase->in_snd_device = in_snd_device;
1675 usecase->out_snd_device = out_snd_device;
1676
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301677 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1678 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301679 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001680 if ((24 == usecase->stream.out->bit_width) &&
1681 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1682 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1683 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1684 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1685 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1686 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1687 /*
1688 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1689 * configured device sample rate, if not update the COPP rate to be equal to the
1690 * device sample rate, else open COPP at stream sample rate
1691 */
1692 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1693 usecase->stream.out->sample_rate,
1694 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301695 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1696 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001697 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1698 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1699 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1700 }
1701
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001702 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001703 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001704 audio_extn_gef_notify_device_config(
1705 usecase->stream.out->devices,
1706 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001707 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001708 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001709 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301710 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001711 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001712
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001713 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001714 /* Enable aanc only if voice call exists */
1715 if (voice_is_call_state_active(adev))
1716 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1717
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001718 /* Enable sidetone only if other voice/voip call already exists */
1719 if (voice_is_call_state_active(adev) ||
1720 voice_extn_compress_voip_is_started(adev))
1721 voice_set_sidetone(adev, out_snd_device, true);
1722 }
1723
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001724 /* Applicable only on the targets that has external modem.
1725 * Enable device command should be sent to modem only after
1726 * enabling voice call mixer controls
1727 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001728 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001729 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1730 out_snd_device,
1731 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301732 ALOGD("%s: done",__func__);
1733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734 return status;
1735}
1736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737static int stop_input_stream(struct stream_in *in)
1738{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301739 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740 struct audio_usecase *uc_info;
1741 struct audio_device *adev = in->dev;
1742
Eric Laurent994a6932013-07-17 11:51:42 -07001743 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001744 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 uc_info = get_usecase_from_list(adev, in->usecase);
1746 if (uc_info == NULL) {
1747 ALOGE("%s: Could not find the usecase (%d) in the list",
1748 __func__, in->usecase);
1749 return -EINVAL;
1750 }
1751
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001752 /* Close in-call recording streams */
1753 voice_check_and_stop_incall_rec_usecase(adev, in);
1754
Eric Laurent150dbfe2013-02-27 14:31:02 -08001755 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001756 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001757
1758 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001759 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001761 list_remove(&uc_info->list);
1762 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001764 adev->active_input = get_next_active_input(adev);
1765
Eric Laurent994a6932013-07-17 11:51:42 -07001766 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 return ret;
1768}
1769
1770int start_input_stream(struct stream_in *in)
1771{
1772 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001773 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 struct audio_usecase *uc_info;
1775 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301776 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777
Mingming Yin2664a5b2015-09-03 10:53:11 -07001778 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1779 if (get_usecase_from_list(adev, usecase) == NULL)
1780 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301781 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1782 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001783
Naresh Tanniru80659832014-06-04 18:17:56 +05301784
1785 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301786 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301787 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301788 goto error_config;
1789 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301790
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001791 /* Check if source matches incall recording usecase criteria */
1792 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1793 if (ret)
1794 goto error_config;
1795 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001796 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1797
1798 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1799 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1800 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001801 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001802 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001803
Eric Laurentb23d5282013-05-14 15:27:20 -07001804 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 if (in->pcm_device_id < 0) {
1806 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1807 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001808 ret = -EINVAL;
1809 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811
1812 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001814
1815 if (!uc_info) {
1816 ret = -ENOMEM;
1817 goto error_config;
1818 }
1819
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820 uc_info->id = in->usecase;
1821 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001822 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 uc_info->devices = in->device;
1824 uc_info->in_snd_device = SND_DEVICE_NONE;
1825 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001827 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301828 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1829 adev->perf_lock_opts,
1830 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301833 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1834 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001835
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301836 if (audio_extn_cin_attached_usecase(in->usecase)) {
1837 ret = audio_extn_cin_start_input_stream(in);
1838 if (ret)
1839 goto error_open;
1840 else
1841 goto done_open;
1842 }
1843
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001844 unsigned int flags = PCM_IN;
1845 unsigned int pcm_open_retry_count = 0;
1846
1847 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1848 flags |= PCM_MMAP | PCM_NOIRQ;
1849 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001850 } else if (in->realtime) {
1851 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001852 }
1853
1854 while (1) {
1855 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1856 flags, &in->config);
1857 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1858 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1859 if (in->pcm != NULL) {
1860 pcm_close(in->pcm);
1861 in->pcm = NULL;
1862 }
1863 if (pcm_open_retry_count-- == 0) {
1864 ret = -EIO;
1865 goto error_open;
1866 }
1867 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1868 continue;
1869 }
1870 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001872
1873 ALOGV("%s: pcm_prepare", __func__);
1874 ret = pcm_prepare(in->pcm);
1875 if (ret < 0) {
1876 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1877 pcm_close(in->pcm);
1878 in->pcm = NULL;
1879 goto error_open;
1880 }
1881
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001882 register_in_stream(in);
1883 if (in->realtime) {
1884 ret = pcm_start(in->pcm);
1885 if (ret < 0)
1886 goto error_open;
1887 }
1888
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301889done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301890 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001891 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001892
Eric Laurentc8400632013-02-14 19:04:54 -08001893 return ret;
1894
1895error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301896 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001898error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301899 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301900 /*
1901 * sleep 50ms to allow sufficient time for kernel
1902 * drivers to recover incases like SSR.
1903 */
1904 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001905 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001906
1907 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908}
1909
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001910void lock_input_stream(struct stream_in *in)
1911{
1912 pthread_mutex_lock(&in->pre_lock);
1913 pthread_mutex_lock(&in->lock);
1914 pthread_mutex_unlock(&in->pre_lock);
1915}
1916
1917void lock_output_stream(struct stream_out *out)
1918{
1919 pthread_mutex_lock(&out->pre_lock);
1920 pthread_mutex_lock(&out->lock);
1921 pthread_mutex_unlock(&out->pre_lock);
1922}
1923
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924/* must be called with out->lock locked */
1925static int send_offload_cmd_l(struct stream_out* out, int command)
1926{
1927 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1928
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001929 if (!cmd) {
1930 ALOGE("failed to allocate mem for command 0x%x", command);
1931 return -ENOMEM;
1932 }
1933
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934 ALOGVV("%s %d", __func__, command);
1935
1936 cmd->cmd = command;
1937 list_add_tail(&out->offload_cmd_list, &cmd->node);
1938 pthread_cond_signal(&out->offload_cond);
1939 return 0;
1940}
1941
1942/* must be called iwth out->lock locked */
1943static void stop_compressed_output_l(struct stream_out *out)
1944{
1945 out->offload_state = OFFLOAD_STATE_IDLE;
1946 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001947 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001948 if (out->compr != NULL) {
1949 compress_stop(out->compr);
1950 while (out->offload_thread_blocked) {
1951 pthread_cond_wait(&out->cond, &out->lock);
1952 }
1953 }
1954}
1955
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001956bool is_offload_usecase(audio_usecase_t uc_id)
1957{
1958 unsigned int i;
1959 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1960 if (uc_id == offload_usecases[i])
1961 return true;
1962 }
1963 return false;
1964}
1965
Dhananjay Kumarac341582017-02-23 23:42:25 +05301966static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001967{
vivek mehta446c3962015-09-14 10:57:35 -07001968 audio_usecase_t ret_uc = USECASE_INVALID;
1969 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001970 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001971 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301972 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001973 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1974 else
1975 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001976
vivek mehta446c3962015-09-14 10:57:35 -07001977 pthread_mutex_lock(&adev->lock);
1978 if (get_usecase_from_list(adev, ret_uc) != NULL)
1979 ret_uc = USECASE_INVALID;
1980 pthread_mutex_unlock(&adev->lock);
1981
1982 return ret_uc;
1983 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001984
1985 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001986 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1987 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1988 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1989 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001990 break;
1991 }
1992 }
vivek mehta446c3962015-09-14 10:57:35 -07001993
1994 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1995 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001996}
1997
1998static void free_offload_usecase(struct audio_device *adev,
1999 audio_usecase_t uc_id)
2000{
vivek mehta446c3962015-09-14 10:57:35 -07002001 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002002 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002003
2004 if (!adev->multi_offload_enable)
2005 return;
2006
2007 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2008 if (offload_usecases[offload_uc_index] == uc_id) {
2009 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002010 break;
2011 }
2012 }
2013 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2014}
2015
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016static void *offload_thread_loop(void *context)
2017{
2018 struct stream_out *out = (struct stream_out *) context;
2019 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002020 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2023 set_sched_policy(0, SP_FOREGROUND);
2024 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2025
2026 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002027 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002028 for (;;) {
2029 struct offload_cmd *cmd = NULL;
2030 stream_callback_event_t event;
2031 bool send_callback = false;
2032
2033 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2034 __func__, list_empty(&out->offload_cmd_list),
2035 out->offload_state);
2036 if (list_empty(&out->offload_cmd_list)) {
2037 ALOGV("%s SLEEPING", __func__);
2038 pthread_cond_wait(&out->offload_cond, &out->lock);
2039 ALOGV("%s RUNNING", __func__);
2040 continue;
2041 }
2042
2043 item = list_head(&out->offload_cmd_list);
2044 cmd = node_to_item(item, struct offload_cmd, node);
2045 list_remove(item);
2046
2047 ALOGVV("%s STATE %d CMD %d out->compr %p",
2048 __func__, out->offload_state, cmd->cmd, out->compr);
2049
2050 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2051 free(cmd);
2052 break;
2053 }
2054
2055 if (out->compr == NULL) {
2056 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002057 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 pthread_cond_signal(&out->cond);
2059 continue;
2060 }
2061 out->offload_thread_blocked = true;
2062 pthread_mutex_unlock(&out->lock);
2063 send_callback = false;
2064 switch(cmd->cmd) {
2065 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002066 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002067 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002068 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069 send_callback = true;
2070 event = STREAM_CBK_EVENT_WRITE_READY;
2071 break;
2072 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002073 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302074 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002075 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302076 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002077 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302078 if (ret < 0)
2079 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302080 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302081 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002082 compress_drain(out->compr);
2083 else
2084 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302085 if (ret != -ENETRESET) {
2086 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302087 pthread_mutex_lock(&out->lock);
2088 out->send_new_metadata = 1;
2089 out->send_next_track_params = true;
2090 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302091 event = STREAM_CBK_EVENT_DRAIN_READY;
2092 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2093 } else
2094 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 break;
2096 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002097 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002099 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002100 send_callback = true;
2101 event = STREAM_CBK_EVENT_DRAIN_READY;
2102 break;
2103 default:
2104 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2105 break;
2106 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002107 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 out->offload_thread_blocked = false;
2109 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002110 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002111 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002113 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114 free(cmd);
2115 }
2116
2117 pthread_cond_signal(&out->cond);
2118 while (!list_empty(&out->offload_cmd_list)) {
2119 item = list_head(&out->offload_cmd_list);
2120 list_remove(item);
2121 free(node_to_item(item, struct offload_cmd, node));
2122 }
2123 pthread_mutex_unlock(&out->lock);
2124
2125 return NULL;
2126}
2127
2128static int create_offload_callback_thread(struct stream_out *out)
2129{
2130 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2131 list_init(&out->offload_cmd_list);
2132 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2133 offload_thread_loop, out);
2134 return 0;
2135}
2136
2137static int destroy_offload_callback_thread(struct stream_out *out)
2138{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002139 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002140 stop_compressed_output_l(out);
2141 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2142
2143 pthread_mutex_unlock(&out->lock);
2144 pthread_join(out->offload_thread, (void **) NULL);
2145 pthread_cond_destroy(&out->offload_cond);
2146
2147 return 0;
2148}
2149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150static int stop_output_stream(struct stream_out *out)
2151{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302152 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 struct audio_usecase *uc_info;
2154 struct audio_device *adev = out->dev;
2155
Eric Laurent994a6932013-07-17 11:51:42 -07002156 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002157 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 uc_info = get_usecase_from_list(adev, out->usecase);
2159 if (uc_info == NULL) {
2160 ALOGE("%s: Could not find the usecase (%d) in the list",
2161 __func__, out->usecase);
2162 return -EINVAL;
2163 }
2164
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002165 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302166 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002167 if (adev->visualizer_stop_output != NULL)
2168 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002169
2170 audio_extn_dts_remove_state_notifier_node(out->usecase);
2171
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002172 if (adev->offload_effects_stop_output != NULL)
2173 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2174 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002175
Eric Laurent150dbfe2013-02-27 14:31:02 -08002176 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002177 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002178
2179 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002180 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002182 list_remove(&uc_info->list);
2183 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002184
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002185 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302186 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002187 ALOGV("Disable passthrough , reset mixer to pcm");
2188 /* NO_PASSTHROUGH */
2189 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002190 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002191 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2192 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002193
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302194 /* Must be called after removing the usecase from list */
2195 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302196 audio_extn_keep_alive_start();
2197
Manish Dewangan14956cc2017-02-14 18:54:42 +05302198 /*reset delay_param to 0*/
2199 out->delay_param.start_delay = 0;
2200
Eric Laurent994a6932013-07-17 11:51:42 -07002201 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 return ret;
2203}
2204
2205int start_output_stream(struct stream_out *out)
2206{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 struct audio_usecase *uc_info;
2209 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302210 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002211 char mixer_ctl_name[128];
2212 struct mixer_ctl *ctl = NULL;
2213 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002215 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2216 ret = -EINVAL;
2217 goto error_config;
2218 }
2219
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302220 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2221 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2222 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302223
Naresh Tanniru80659832014-06-04 18:17:56 +05302224 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302225 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302226 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302227 goto error_config;
2228 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302229
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302230 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2231 if (!audio_extn_a2dp_is_ready()) {
2232 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2233 //combo usecase just by pass a2dp
2234 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2235 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2236 } else {
2237 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2238 ret = -EAGAIN;
2239 goto error_config;
2240 }
2241 }
2242 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002243 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 if (out->pcm_device_id < 0) {
2245 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2246 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002247 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002248 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 }
2250
2251 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002252
2253 if (!uc_info) {
2254 ret = -ENOMEM;
2255 goto error_config;
2256 }
2257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 uc_info->id = out->usecase;
2259 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002260 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002261 uc_info->devices = out->devices;
2262 uc_info->in_snd_device = SND_DEVICE_NONE;
2263 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002264 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302266 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2267 adev->perf_lock_opts,
2268 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302269
2270 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2271 audio_extn_keep_alive_stop();
2272 if (audio_extn_passthru_is_enabled() &&
2273 audio_extn_passthru_is_passthrough_stream(out)) {
2274 audio_extn_passthru_on_start(out);
2275 audio_extn_passthru_update_stream_configuration(adev, out);
2276 }
2277 }
2278
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002279 select_devices(adev, out->usecase);
2280
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002281 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2282 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002283 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002284 unsigned int flags = PCM_OUT;
2285 unsigned int pcm_open_retry_count = 0;
2286 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2287 flags |= PCM_MMAP | PCM_NOIRQ;
2288 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002289 } else if (out->realtime) {
2290 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002291 } else
2292 flags |= PCM_MONOTONIC;
2293
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002294 if ((adev->vr_audio_mode_enabled) &&
2295 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2296 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2297 "PCM_Dev %d Topology", out->pcm_device_id);
2298 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2299 if (!ctl) {
2300 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2301 __func__, mixer_ctl_name);
2302 } else {
2303 //if success use ULLPP
2304 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2305 __func__, mixer_ctl_name, out->pcm_device_id);
2306 //There is a still a possibility that some sessions
2307 // that request for FAST|RAW when 3D audio is active
2308 //can go through ULLPP. Ideally we expects apps to
2309 //listen to audio focus and stop concurrent playback
2310 //Also, we will look for mode flag (voice_in_communication)
2311 //before enabling the realtime flag.
2312 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2313 }
2314 }
2315
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002316 while (1) {
2317 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2318 flags, &out->config);
2319 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2320 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2321 if (out->pcm != NULL) {
2322 pcm_close(out->pcm);
2323 out->pcm = NULL;
2324 }
2325 if (pcm_open_retry_count-- == 0) {
2326 ret = -EIO;
2327 goto error_open;
2328 }
2329 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2330 continue;
2331 }
2332 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002334
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002335 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2336 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002337
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002338 ALOGV("%s: pcm_prepare", __func__);
2339 if (pcm_is_ready(out->pcm)) {
2340 ret = pcm_prepare(out->pcm);
2341 if (ret < 0) {
2342 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2343 pcm_close(out->pcm);
2344 out->pcm = NULL;
2345 goto error_open;
2346 }
2347 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302348 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2349 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002350 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002351 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2352 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002354 out->compr = compress_open(adev->snd_card,
2355 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 COMPRESS_IN, &out->compr_config);
2357 if (out->compr && !is_compress_ready(out->compr)) {
2358 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2359 compress_close(out->compr);
2360 out->compr = NULL;
2361 ret = -EIO;
2362 goto error_open;
2363 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302364 /* compress_open sends params of the track, so reset the flag here */
2365 out->is_compr_metadata_avail = false;
2366
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 if (out->offload_callback)
2368 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002369
Fred Oh3f43e742015-03-04 18:42:34 -08002370 /* Since small bufs uses blocking writes, a write will be blocked
2371 for the default max poll time (20s) in the event of an SSR.
2372 Reduce the poll time to observe and deal with SSR faster.
2373 */
Ashish Jain5106d362016-05-11 19:23:33 +05302374 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002375 compress_set_max_poll_wait(out->compr, 1000);
2376 }
2377
Manish Dewangan69426c82017-01-30 17:35:36 +05302378 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302379 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan27346042017-03-01 12:56:12 +05302380 /* set render window if it was set before compress_open() */
2381 if (out->render_window.render_ws != 0 && out->render_window.render_we != 0)
2382 audio_extn_utils_compress_set_render_window(out,
2383 &out->render_window);
Manish Dewangan14956cc2017-02-14 18:54:42 +05302384 audio_extn_utils_compress_set_start_delay(out, &out->delay_param);
Manish Dewangan69426c82017-01-30 17:35:36 +05302385
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002386 audio_extn_dts_create_state_notifier_node(out->usecase);
2387 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2388 popcount(out->channel_mask),
2389 out->playback_started);
2390
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002391#ifdef DS1_DOLBY_DDP_ENABLED
2392 if (audio_extn_is_dolby_format(out->format))
2393 audio_extn_dolby_send_ddp_endp_params(adev);
2394#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302395 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2396 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002397 if (adev->visualizer_start_output != NULL)
2398 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2399 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302400 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002401 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002404
2405 if (ret == 0) {
2406 register_out_stream(out);
2407 if (out->realtime) {
2408 ret = pcm_start(out->pcm);
2409 if (ret < 0)
2410 goto error_open;
2411 }
2412 }
2413
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302414 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002415 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002416
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002417 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002418error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302419 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002421error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302422 /*
2423 * sleep 50ms to allow sufficient time for kernel
2424 * drivers to recover incases like SSR.
2425 */
2426 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002427 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428}
2429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430static int check_input_parameters(uint32_t sample_rate,
2431 audio_format_t format,
2432 int channel_count)
2433{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002434 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302436 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2437 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2438 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002439 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302440 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002441
2442 switch (channel_count) {
2443 case 1:
2444 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302445 case 3:
2446 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002447 case 6:
2448 break;
2449 default:
2450 ret = -EINVAL;
2451 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452
2453 switch (sample_rate) {
2454 case 8000:
2455 case 11025:
2456 case 12000:
2457 case 16000:
2458 case 22050:
2459 case 24000:
2460 case 32000:
2461 case 44100:
2462 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302463 case 96000:
2464 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 break;
2466 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002467 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 }
2469
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002470 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471}
2472
2473static size_t get_input_buffer_size(uint32_t sample_rate,
2474 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002475 int channel_count,
2476 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477{
2478 size_t size = 0;
2479
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002480 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2481 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002483 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002484 if (is_low_latency)
2485 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302486
2487 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002489 /* make sure the size is multiple of 32 bytes
2490 * At 48 kHz mono 16-bit PCM:
2491 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2492 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2493 */
2494 size += 0x1f;
2495 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002496
2497 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498}
2499
Ashish Jain058165c2016-09-28 23:18:48 +05302500static size_t get_output_period_size(uint32_t sample_rate,
2501 audio_format_t format,
2502 int channel_count,
2503 int duration /*in millisecs*/)
2504{
2505 size_t size = 0;
2506 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2507
2508 if ((duration == 0) || (sample_rate == 0) ||
2509 (bytes_per_sample == 0) || (channel_count == 0)) {
2510 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2511 bytes_per_sample, channel_count);
2512 return -EINVAL;
2513 }
2514
2515 size = (sample_rate *
2516 duration *
2517 bytes_per_sample *
2518 channel_count) / 1000;
2519 /*
2520 * To have same PCM samples for all channels, the buffer size requires to
2521 * be multiple of (number of channels * bytes per sample)
2522 * For writes to succeed, the buffer must be written at address which is multiple of 32
2523 */
2524 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2525
2526 return (size/(channel_count * bytes_per_sample));
2527}
2528
Ashish Jain5106d362016-05-11 19:23:33 +05302529static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2530{
2531 uint64_t actual_frames_rendered = 0;
2532 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2533
2534 /* This adjustment accounts for buffering after app processor.
2535 * It is based on estimated DSP latency per use case, rather than exact.
2536 */
2537 int64_t platform_latency = platform_render_latency(out->usecase) *
2538 out->sample_rate / 1000000LL;
2539
2540 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2541 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2542 * hence only estimate.
2543 */
2544 int64_t signed_frames = out->written - kernel_buffer_size;
2545
2546 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2547
2548 if (signed_frames > 0)
2549 actual_frames_rendered = signed_frames;
2550
2551 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2552 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2553 (long long int)out->written, (int)kernel_buffer_size,
2554 audio_bytes_per_sample(out->compr_config.codec->format),
2555 popcount(out->channel_mask));
2556
2557 return actual_frames_rendered;
2558}
2559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2561{
2562 struct stream_out *out = (struct stream_out *)stream;
2563
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002564 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565}
2566
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002567static int out_set_sample_rate(struct audio_stream *stream __unused,
2568 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569{
2570 return -ENOSYS;
2571}
2572
2573static size_t out_get_buffer_size(const struct audio_stream *stream)
2574{
2575 struct stream_out *out = (struct stream_out *)stream;
2576
Dhananjay Kumarac341582017-02-23 23:42:25 +05302577 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002578 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002579 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2580 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302581 else if (is_offload_usecase(out->usecase) &&
2582 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302583 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002585 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002586 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587}
2588
2589static uint32_t out_get_channels(const struct audio_stream *stream)
2590{
2591 struct stream_out *out = (struct stream_out *)stream;
2592
2593 return out->channel_mask;
2594}
2595
2596static audio_format_t out_get_format(const struct audio_stream *stream)
2597{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 struct stream_out *out = (struct stream_out *)stream;
2599
2600 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601}
2602
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002603static int out_set_format(struct audio_stream *stream __unused,
2604 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605{
2606 return -ENOSYS;
2607}
2608
2609static int out_standby(struct audio_stream *stream)
2610{
2611 struct stream_out *out = (struct stream_out *)stream;
2612 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002613
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302614 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2615 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002617 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002619 if (adev->adm_deregister_stream)
2620 adev->adm_deregister_stream(adev->adm_data, out->handle);
2621
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002622 if (is_offload_usecase(out->usecase))
2623 stop_compressed_output_l(out);
2624
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002625 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002627 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2628 voice_extn_compress_voip_close_output_stream(stream);
2629 pthread_mutex_unlock(&adev->lock);
2630 pthread_mutex_unlock(&out->lock);
2631 ALOGD("VOIP output entered standby");
2632 return 0;
2633 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 if (out->pcm) {
2635 pcm_close(out->pcm);
2636 out->pcm = NULL;
2637 }
2638 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002639 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302640 out->send_next_track_params = false;
2641 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002642 out->gapless_mdata.encoder_delay = 0;
2643 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002644 if (out->compr != NULL) {
2645 compress_close(out->compr);
2646 out->compr = NULL;
2647 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002648 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002650 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 }
2652 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302653 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 return 0;
2655}
2656
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002657static int out_dump(const struct audio_stream *stream __unused,
2658 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659{
2660 return 0;
2661}
2662
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002663static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2664{
2665 int ret = 0;
2666 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002667
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002668 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002669 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002670 return -EINVAL;
2671 }
2672
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302673 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002674
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002675 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2676 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302677 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002678 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002679 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2680 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302681 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002682 }
2683
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002684 ALOGV("%s new encoder delay %u and padding %u", __func__,
2685 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2686
2687 return 0;
2688}
2689
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002690static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2691{
2692 return out == adev->primary_output || out == adev->voice_tx_output;
2693}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2696{
2697 struct stream_out *out = (struct stream_out *)stream;
2698 struct audio_device *adev = out->dev;
2699 struct str_parms *parms;
2700 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002701 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702
sangwoobc677242013-08-08 16:53:43 +09002703 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002704 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302706 if (!parms)
2707 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002708 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2709 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002711 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002712 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002714 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002715 * When HDMI cable is unplugged the music playback is paused and
2716 * the policy manager sends routing=0. But the audioflinger continues
2717 * to write data until standby time (3sec). As the HDMI core is
2718 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002719 * Avoid this by routing audio to speaker until standby.
2720 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002721 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2722 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302723 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002724 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2725 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002726 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302727 /*
2728 * When A2DP is disconnected the
2729 * music playback is paused and the policy manager sends routing=0
2730 * But the audioflingercontinues to write data until standby time
2731 * (3sec). As BT is turned off, the write gets blocked.
2732 * Avoid this by routing audio to speaker until standby.
2733 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002734 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302735 (val == AUDIO_DEVICE_NONE)) {
2736 val = AUDIO_DEVICE_OUT_SPEAKER;
2737 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302738 /* To avoid a2dp to sco overlapping / BT device improper state
2739 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302740 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302741 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2742 if (!audio_extn_a2dp_is_ready()) {
2743 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2744 //combo usecase just by pass a2dp
2745 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2746 val = AUDIO_DEVICE_OUT_SPEAKER;
2747 } else {
2748 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2749 /* update device to a2dp and don't route as BT returned error
2750 * However it is still possible a2dp routing called because
2751 * of current active device disconnection (like wired headset)
2752 */
2753 out->devices = val;
2754 pthread_mutex_unlock(&out->lock);
2755 pthread_mutex_unlock(&adev->lock);
2756 goto error;
2757 }
2758 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002760 /*
2761 * select_devices() call below switches all the usecases on the same
2762 * backend to the new device. Refer to check_usecases_codec_backend() in
2763 * the select_devices(). But how do we undo this?
2764 *
2765 * For example, music playback is active on headset (deep-buffer usecase)
2766 * and if we go to ringtones and select a ringtone, low-latency usecase
2767 * will be started on headset+speaker. As we can't enable headset+speaker
2768 * and headset devices at the same time, select_devices() switches the music
2769 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2770 * So when the ringtone playback is completed, how do we undo the same?
2771 *
2772 * We are relying on the out_set_parameters() call on deep-buffer output,
2773 * once the ringtone playback is ended.
2774 * NOTE: We should not check if the current devices are same as new devices.
2775 * Because select_devices() must be called to switch back the music
2776 * playback to headset.
2777 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002778 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002779 audio_devices_t new_dev = val;
2780 bool same_dev = out->devices == new_dev;
2781 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002782
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002783 if (output_drives_call(adev, out)) {
2784 if(!voice_is_in_call(adev)) {
2785 if (adev->mode == AUDIO_MODE_IN_CALL) {
2786 adev->current_call_output = out;
2787 ret = voice_start_call(adev);
2788 }
2789 } else {
2790 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002791 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002792 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002793 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002794
2795 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002796 if (!same_dev) {
2797 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302798 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2799 adev->perf_lock_opts,
2800 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002801 if (adev->adm_on_routing_change)
2802 adev->adm_on_routing_change(adev->adm_data,
2803 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002804 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002805 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302806 if (!same_dev)
2807 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002808 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002809 }
2810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002812 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002814
2815 if (out == adev->primary_output) {
2816 pthread_mutex_lock(&adev->lock);
2817 audio_extn_set_parameters(adev, parms);
2818 pthread_mutex_unlock(&adev->lock);
2819 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002820 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002821 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002822 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002823
2824 audio_extn_dts_create_state_notifier_node(out->usecase);
2825 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2826 popcount(out->channel_mask),
2827 out->playback_started);
2828
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002829 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002830 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002831
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302832 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2833 if (err >= 0) {
2834 strlcpy(out->profile, value, sizeof(out->profile));
2835 ALOGV("updating stream profile with value '%s'", out->profile);
2836 lock_output_stream(out);
2837 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2838 &adev->streams_output_cfg_list,
2839 out->devices, out->flags, out->format,
2840 out->sample_rate, out->bit_width,
2841 out->channel_mask, out->profile,
2842 &out->app_type_cfg);
2843 pthread_mutex_unlock(&out->lock);
2844 }
2845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302847error:
Eric Laurent994a6932013-07-17 11:51:42 -07002848 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 return ret;
2850}
2851
2852static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2853{
2854 struct stream_out *out = (struct stream_out *)stream;
2855 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002856 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 char value[256];
2858 struct str_parms *reply = str_parms_create();
2859 size_t i, j;
2860 int ret;
2861 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002862
2863 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002864 if (reply) {
2865 str_parms_destroy(reply);
2866 }
2867 if (query) {
2868 str_parms_destroy(query);
2869 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002870 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2871 return NULL;
2872 }
2873
Eric Laurent994a6932013-07-17 11:51:42 -07002874 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2876 if (ret >= 0) {
2877 value[0] = '\0';
2878 i = 0;
2879 while (out->supported_channel_masks[i] != 0) {
2880 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2881 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2882 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002883 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002885 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 first = false;
2887 break;
2888 }
2889 }
2890 i++;
2891 }
2892 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2893 str = str_parms_to_str(reply);
2894 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002895 voice_extn_out_get_parameters(out, query, reply);
2896 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002897 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002898 free(str);
2899 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002900 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002901 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002902
Alexy Joseph62142aa2015-11-16 15:10:34 -08002903
2904 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2905 if (ret >= 0) {
2906 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302907 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2908 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002909 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302910 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002911 } else {
2912 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302913 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002914 }
2915 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002916 if (str)
2917 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002918 str = str_parms_to_str(reply);
2919 }
2920
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002921 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2922 if (ret >= 0) {
2923 value[0] = '\0';
2924 i = 0;
2925 first = true;
2926 while (out->supported_formats[i] != 0) {
2927 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2928 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2929 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002930 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002931 }
2932 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2933 first = false;
2934 break;
2935 }
2936 }
2937 i++;
2938 }
2939 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002940 if (str)
2941 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002942 str = str_parms_to_str(reply);
2943 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002944
2945 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2946 if (ret >= 0) {
2947 value[0] = '\0';
2948 i = 0;
2949 first = true;
2950 while (out->supported_sample_rates[i] != 0) {
2951 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2952 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2953 if (!first) {
2954 strlcat(value, "|", sizeof(value));
2955 }
2956 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2957 first = false;
2958 break;
2959 }
2960 }
2961 i++;
2962 }
2963 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2964 if (str)
2965 free(str);
2966 str = str_parms_to_str(reply);
2967 }
2968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002969 str_parms_destroy(query);
2970 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002971 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 return str;
2973}
2974
2975static uint32_t out_get_latency(const struct audio_stream_out *stream)
2976{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002977 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002979 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980
Alexy Josephaa54c872014-12-03 02:46:47 -08002981 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302982 lock_output_stream(out);
2983 latency = audio_extn_utils_compress_get_dsp_latency(out);
2984 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002985 } else if (out->realtime) {
2986 // since the buffer won't be filled up faster than realtime,
2987 // return a smaller number
2988 if (out->config.rate)
2989 period_ms = (out->af_period_multiplier * out->config.period_size *
2990 1000) / (out->config.rate);
2991 else
2992 period_ms = 0;
2993 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002994 } else {
2995 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002997 }
2998
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002999 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3000 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3001 latency += audio_extn_a2dp_get_encoder_latency();
3002
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303003 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003004 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005}
3006
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303007static float AmpToDb(float amplification)
3008{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303009 float db = DSD_VOLUME_MIN_DB;
3010 if (amplification > 0) {
3011 db = 20 * log10(amplification);
3012 if(db < DSD_VOLUME_MIN_DB)
3013 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303014 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303015 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303016}
3017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018static int out_set_volume(struct audio_stream_out *stream, float left,
3019 float right)
3020{
Eric Laurenta9024de2013-04-04 09:19:12 -07003021 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 int volume[2];
3023
Eric Laurenta9024de2013-04-04 09:19:12 -07003024 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3025 /* only take left channel into account: the API is for stereo anyway */
3026 out->muted = (left == 0.0f);
3027 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003028 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303029 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003030 /*
3031 * Set mute or umute on HDMI passthrough stream.
3032 * Only take left channel into account.
3033 * Mute is 0 and unmute 1
3034 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303035 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303036 } else if (out->format == AUDIO_FORMAT_DSD){
3037 char mixer_ctl_name[128] = "DSD Volume";
3038 struct audio_device *adev = out->dev;
3039 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3040
3041 if (!ctl) {
3042 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3043 __func__, mixer_ctl_name);
3044 return -EINVAL;
3045 }
3046 volume[0] = (int)(AmpToDb(left));
3047 volume[1] = (int)(AmpToDb(right));
3048 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3049 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003050 } else {
3051 char mixer_ctl_name[128];
3052 struct audio_device *adev = out->dev;
3053 struct mixer_ctl *ctl;
3054 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003055 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003057 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3058 "Compress Playback %d Volume", pcm_device_id);
3059 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3060 if (!ctl) {
3061 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3062 __func__, mixer_ctl_name);
3063 return -EINVAL;
3064 }
3065 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3066 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3067 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3068 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003069 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003070 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072 return -ENOSYS;
3073}
3074
3075static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3076 size_t bytes)
3077{
3078 struct stream_out *out = (struct stream_out *)stream;
3079 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303080 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003081 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003083 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303084
Naresh Tanniru80659832014-06-04 18:17:56 +05303085 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003086
Dhananjay Kumarac341582017-02-23 23:42:25 +05303087 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303088 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303089 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3090 pthread_mutex_unlock(&out->lock);
3091 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303092 } else {
3093 /* increase written size during SSR to avoid mismatch
3094 * with the written frames count in AF
3095 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003096 // bytes per frame
3097 size_t bpf = audio_bytes_per_sample(out->format) *
3098 audio_channel_count_from_out_mask(out->channel_mask);
3099 if (bpf != 0)
3100 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303101 ALOGD(" %s: sound card is not active/SSR state", __func__);
3102 ret= -EIO;
3103 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303104 }
3105 }
3106
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303107 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303108 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3109 if (audio_bytes_per_sample(out->format) != 0)
3110 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3111 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303112 goto exit;
3113 }
3114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003116 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003117 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003118 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3119 ret = voice_extn_compress_voip_start_output_stream(out);
3120 else
3121 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003122 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003123 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003125 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 goto exit;
3127 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003128
3129 if (last_known_cal_step != -1) {
3130 ALOGD("%s: retry previous failed cal level set", __func__);
3131 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3132 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
Ashish Jain81eb2a82015-05-13 10:52:34 +05303135 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003136 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303137 adev->is_channel_status_set = true;
3138 }
3139
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003140 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003141 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003142 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003143 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003144 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3145 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303146 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3147 ALOGD("copl(%p):send next track params in gapless", out);
3148 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3149 out->send_next_track_params = false;
3150 out->is_compr_metadata_avail = false;
3151 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003152 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303153 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303154 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003155
Ashish Jain83a6cc22016-06-28 14:34:17 +05303156 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303157 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303158 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303159 pthread_mutex_unlock(&out->lock);
3160 return -EINVAL;
3161 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303162 audio_format_t dst_format = out->hal_op_format;
3163 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303164
3165 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3166 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3167
Ashish Jain83a6cc22016-06-28 14:34:17 +05303168 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303169 dst_format,
3170 buffer,
3171 src_format,
3172 frames);
3173
Ashish Jain83a6cc22016-06-28 14:34:17 +05303174 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303175 bytes_to_write);
3176
3177 /*Convert written bytes in audio flinger format*/
3178 if (ret > 0)
3179 ret = ((ret * format_to_bitwidth_table[out->format]) /
3180 format_to_bitwidth_table[dst_format]);
3181 }
3182 } else
3183 ret = compress_write(out->compr, buffer, bytes);
3184
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303185 if (ret < 0)
3186 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303187 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303188 /*msg to cb thread only if non blocking write is enabled*/
3189 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303190 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303192 } else if (-ENETRESET == ret) {
3193 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3194 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3195 pthread_mutex_unlock(&out->lock);
3196 out_standby(&out->stream.common);
3197 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003198 }
Ashish Jain5106d362016-05-11 19:23:33 +05303199 if ( ret == (ssize_t)bytes && !out->non_blocking)
3200 out->written += bytes;
3201
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303202 /* Call compr start only when non-zero bytes of data is there to be rendered */
3203 if (!out->playback_started && ret > 0) {
3204 int status = compress_start(out->compr);
3205 if (status < 0) {
3206 ret = status;
3207 ALOGE("%s: compr start failed with err %d", __func__, errno);
3208 goto exit;
3209 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003210 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003211 out->playback_started = 1;
3212 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003213
3214 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3215 popcount(out->channel_mask),
3216 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 }
3218 pthread_mutex_unlock(&out->lock);
3219 return ret;
3220 } else {
3221 if (out->pcm) {
3222 if (out->muted)
3223 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003224
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303225 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003226
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003227 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003228
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003229 if (out->config.rate)
3230 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3231 out->config.rate;
3232
3233 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3234
3235 request_out_focus(out, ns);
3236
3237 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003238 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003239 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303240 out->convert_buffer != NULL) {
3241
3242 memcpy_by_audio_format(out->convert_buffer,
3243 out->hal_op_format,
3244 buffer,
3245 out->hal_ip_format,
3246 out->config.period_size * out->config.channels);
3247
3248 ret = pcm_write(out->pcm, out->convert_buffer,
3249 (out->config.period_size *
3250 out->config.channels *
3251 format_to_bitwidth_table[out->hal_op_format]));
3252 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003253 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303254 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003255
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003256 release_out_focus(out);
3257
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303258 if (ret < 0)
3259 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303260 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3261 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3262 else
3263 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265 }
3266
3267exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303268 /* ToDo: There may be a corner case when SSR happens back to back during
3269 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303270 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303271 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303272 }
3273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 pthread_mutex_unlock(&out->lock);
3275
3276 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003277 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003278 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303279 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303280 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303281 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303282 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303283 out->standby = true;
3284 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303286 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3287 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3288 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 }
3290 return bytes;
3291}
3292
3293static int out_get_render_position(const struct audio_stream_out *stream,
3294 uint32_t *dsp_frames)
3295{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003296 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303297 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003298
3299 if (dsp_frames == NULL)
3300 return -EINVAL;
3301
3302 *dsp_frames = 0;
3303 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003304 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303305
3306 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3307 * this operation and adev_close_output_stream(where out gets reset).
3308 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303309 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303310 *dsp_frames = get_actual_pcm_frames_rendered(out);
3311 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3312 return 0;
3313 }
3314
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003315 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303316 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303317 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003318 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303319 if (ret < 0)
3320 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003321 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303322 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003323 }
3324 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303325 if (-ENETRESET == ret) {
3326 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3327 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3328 return -EINVAL;
3329 } else if(ret < 0) {
3330 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3331 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303332 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3333 /*
3334 * Handle corner case where compress session is closed during SSR
3335 * and timestamp is queried
3336 */
3337 ALOGE(" ERROR: sound card not active, return error");
3338 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303339 } else {
3340 return 0;
3341 }
Zhou Song32a556e2015-05-05 10:46:56 +08003342 } else if (audio_is_linear_pcm(out->format)) {
3343 *dsp_frames = out->written;
3344 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003345 } else
3346 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347}
3348
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003349static int out_add_audio_effect(const struct audio_stream *stream __unused,
3350 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003351{
3352 return 0;
3353}
3354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003355static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3356 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357{
3358 return 0;
3359}
3360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003361static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3362 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363{
3364 return -EINVAL;
3365}
3366
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003367static int out_get_presentation_position(const struct audio_stream_out *stream,
3368 uint64_t *frames, struct timespec *timestamp)
3369{
3370 struct stream_out *out = (struct stream_out *)stream;
3371 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003372 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003373
Ashish Jain5106d362016-05-11 19:23:33 +05303374 /* below piece of code is not guarded against any lock because audioFliner serializes
3375 * this operation and adev_close_output_stream( where out gets reset).
3376 */
3377 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303378 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303379 *frames = get_actual_pcm_frames_rendered(out);
3380 /* this is the best we can do */
3381 clock_gettime(CLOCK_MONOTONIC, timestamp);
3382 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3383 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3384 return 0;
3385 }
3386
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003387 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003388
Ashish Jain5106d362016-05-11 19:23:33 +05303389 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3390 ret = compress_get_tstamp(out->compr, &dsp_frames,
3391 &out->sample_rate);
3392 ALOGVV("%s rendered frames %ld sample_rate %d",
3393 __func__, dsp_frames, out->sample_rate);
3394 *frames = dsp_frames;
3395 if (ret < 0)
3396 ret = -errno;
3397 if (-ENETRESET == ret) {
3398 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3399 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3400 ret = -EINVAL;
3401 } else
3402 ret = 0;
3403 /* this is the best we can do */
3404 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003405 } else {
3406 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003407 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003408 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3409 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003410 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003411 // This adjustment accounts for buffering after app processor.
3412 // It is based on estimated DSP latency per use case, rather than exact.
3413 signed_frames -=
3414 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3415
Eric Laurent949a0892013-09-20 09:20:13 -07003416 // It would be unusual for this value to be negative, but check just in case ...
3417 if (signed_frames >= 0) {
3418 *frames = signed_frames;
3419 ret = 0;
3420 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003421 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303422 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3423 *frames = out->written;
3424 clock_gettime(CLOCK_MONOTONIC, timestamp);
3425 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003426 }
3427 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003428 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003429 return ret;
3430}
3431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432static int out_set_callback(struct audio_stream_out *stream,
3433 stream_callback_t callback, void *cookie)
3434{
3435 struct stream_out *out = (struct stream_out *)stream;
3436
3437 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003438 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003439 out->offload_callback = callback;
3440 out->offload_cookie = cookie;
3441 pthread_mutex_unlock(&out->lock);
3442 return 0;
3443}
3444
3445static int out_pause(struct audio_stream_out* stream)
3446{
3447 struct stream_out *out = (struct stream_out *)stream;
3448 int status = -ENOSYS;
3449 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003450 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003451 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003452 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303454 struct audio_device *adev = out->dev;
3455 int snd_scard_state = get_snd_card_state(adev);
3456
3457 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3458 status = compress_pause(out->compr);
3459
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003460 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003461
Mingming Yin21854652016-04-13 11:54:02 -07003462 if (audio_extn_passthru_is_active()) {
3463 ALOGV("offload use case, pause passthru");
3464 audio_extn_passthru_on_pause(out);
3465 }
3466
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303467 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003468 audio_extn_dts_notify_playback_state(out->usecase, 0,
3469 out->sample_rate, popcount(out->channel_mask),
3470 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 }
3472 pthread_mutex_unlock(&out->lock);
3473 }
3474 return status;
3475}
3476
3477static int out_resume(struct audio_stream_out* stream)
3478{
3479 struct stream_out *out = (struct stream_out *)stream;
3480 int status = -ENOSYS;
3481 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003482 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003483 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003485 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303487 struct audio_device *adev = out->dev;
3488 int snd_scard_state = get_snd_card_state(adev);
3489
Mingming Yin21854652016-04-13 11:54:02 -07003490 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3491 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3492 pthread_mutex_lock(&out->dev->lock);
3493 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003494 pthread_mutex_unlock(&out->dev->lock);
3495 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303496 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003497 }
3498 if (!status) {
3499 out->offload_state = OFFLOAD_STATE_PLAYING;
3500 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303501 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003502 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3503 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 }
3505 pthread_mutex_unlock(&out->lock);
3506 }
3507 return status;
3508}
3509
3510static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3511{
3512 struct stream_out *out = (struct stream_out *)stream;
3513 int status = -ENOSYS;
3514 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003515 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003516 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3518 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3519 else
3520 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3521 pthread_mutex_unlock(&out->lock);
3522 }
3523 return status;
3524}
3525
3526static int out_flush(struct audio_stream_out* stream)
3527{
3528 struct stream_out *out = (struct stream_out *)stream;
3529 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003530 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003531 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003532 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003533 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3534 stop_compressed_output_l(out);
3535 out->written = 0;
3536 } else {
3537 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3538 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003539 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003540 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003541 return 0;
3542 }
3543 return -ENOSYS;
3544}
3545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546/** audio_stream_in implementation **/
3547static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3548{
3549 struct stream_in *in = (struct stream_in *)stream;
3550
3551 return in->config.rate;
3552}
3553
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003554static int in_set_sample_rate(struct audio_stream *stream __unused,
3555 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556{
3557 return -ENOSYS;
3558}
3559
3560static size_t in_get_buffer_size(const struct audio_stream *stream)
3561{
3562 struct stream_in *in = (struct stream_in *)stream;
3563
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003564 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3565 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003566 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3567 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303568 else if(audio_extn_cin_attached_usecase(in->usecase))
3569 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003570
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003571 return in->config.period_size * in->af_period_multiplier *
3572 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573}
3574
3575static uint32_t in_get_channels(const struct audio_stream *stream)
3576{
3577 struct stream_in *in = (struct stream_in *)stream;
3578
3579 return in->channel_mask;
3580}
3581
3582static audio_format_t in_get_format(const struct audio_stream *stream)
3583{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003584 struct stream_in *in = (struct stream_in *)stream;
3585
3586 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587}
3588
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003589static int in_set_format(struct audio_stream *stream __unused,
3590 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591{
3592 return -ENOSYS;
3593}
3594
3595static int in_standby(struct audio_stream *stream)
3596{
3597 struct stream_in *in = (struct stream_in *)stream;
3598 struct audio_device *adev = in->dev;
3599 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303600 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3601 stream, in->usecase, use_case_table[in->usecase]);
3602
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003603 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003604 if (!in->standby && in->is_st_session) {
3605 ALOGD("%s: sound trigger pcm stop lab", __func__);
3606 audio_extn_sound_trigger_stop_lab(in);
3607 in->standby = 1;
3608 }
3609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003611 if (adev->adm_deregister_stream)
3612 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3613
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003614 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003616 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3617 voice_extn_compress_voip_close_input_stream(stream);
3618 ALOGD("VOIP input entered standby");
3619 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303620 if (audio_extn_cin_attached_usecase(in->usecase))
3621 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003622 if (in->pcm) {
3623 pcm_close(in->pcm);
3624 in->pcm = NULL;
3625 }
3626 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003627 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003628 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 }
3630 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003631 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 return status;
3633}
3634
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003635static int in_dump(const struct audio_stream *stream __unused,
3636 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637{
3638 return 0;
3639}
3640
3641static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3642{
3643 struct stream_in *in = (struct stream_in *)stream;
3644 struct audio_device *adev = in->dev;
3645 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003647 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303649 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 parms = str_parms_create_str(kvpairs);
3651
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303652 if (!parms)
3653 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003654 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003655 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003656
3657 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3658 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 val = atoi(value);
3660 /* no audio source uses val == 0 */
3661 if ((in->source != val) && (val != 0)) {
3662 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003663 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3664 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3665 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003666 (in->config.rate == 8000 || in->config.rate == 16000 ||
3667 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003668 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003669 err = voice_extn_compress_voip_open_input_stream(in);
3670 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003671 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003672 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003673 }
3674 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 }
3676 }
3677
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003678 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3679 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003681 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 in->device = val;
3683 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003684 if (!in->standby && !in->is_st_session) {
3685 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003686 if (adev->adm_on_routing_change)
3687 adev->adm_on_routing_change(adev->adm_data,
3688 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003689 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 }
3692 }
3693
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303694 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3695 if (err >= 0) {
3696 strlcpy(in->profile, value, sizeof(in->profile));
3697 ALOGV("updating stream profile with value '%s'", in->profile);
3698 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3699 &adev->streams_input_cfg_list,
3700 in->device, in->flags, in->format,
3701 in->sample_rate, in->bit_width,
3702 in->profile, &in->app_type_cfg);
3703 }
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003706 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707
3708 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303709error:
Eric Laurent994a6932013-07-17 11:51:42 -07003710 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 return ret;
3712}
3713
3714static char* in_get_parameters(const struct audio_stream *stream,
3715 const char *keys)
3716{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003717 struct stream_in *in = (struct stream_in *)stream;
3718 struct str_parms *query = str_parms_create_str(keys);
3719 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003720 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003721
3722 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003723 if (reply) {
3724 str_parms_destroy(reply);
3725 }
3726 if (query) {
3727 str_parms_destroy(query);
3728 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003729 ALOGE("in_get_parameters: failed to create query or reply");
3730 return NULL;
3731 }
3732
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003733 ALOGV("%s: enter: keys - %s", __func__, keys);
3734
3735 voice_extn_in_get_parameters(in, query, reply);
3736
3737 str = str_parms_to_str(reply);
3738 str_parms_destroy(query);
3739 str_parms_destroy(reply);
3740
3741 ALOGV("%s: exit: returns - %s", __func__, str);
3742 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743}
3744
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003745static int in_set_gain(struct audio_stream_in *stream __unused,
3746 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747{
3748 return 0;
3749}
3750
3751static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3752 size_t bytes)
3753{
3754 struct stream_in *in = (struct stream_in *)stream;
3755 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303756 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303757 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303758 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003760 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303761
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003762 if (in->is_st_session) {
3763 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3764 /* Read from sound trigger HAL */
3765 audio_extn_sound_trigger_read(in, buffer, bytes);
3766 pthread_mutex_unlock(&in->lock);
3767 return bytes;
3768 }
3769
Ashish Jainbbce4322016-02-16 13:25:27 +05303770 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003771 ALOGD(" %s: sound card is not active/SSR state", __func__);
3772 ret= -EIO;;
3773 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303774 }
3775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003777 pthread_mutex_lock(&adev->lock);
3778 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3779 ret = voice_extn_compress_voip_start_input_stream(in);
3780 else
3781 ret = start_input_stream(in);
3782 pthread_mutex_unlock(&adev->lock);
3783 if (ret != 0) {
3784 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785 }
3786 in->standby = 0;
3787 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003789 // what's the duration requested by the client?
3790 long ns = 0;
3791
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303792 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003793 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3794 in->config.rate;
3795
3796 request_in_focus(in, ns);
3797 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003798
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303799 if (audio_extn_cin_attached_usecase(in->usecase)) {
3800 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3801 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303802 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003803 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303804 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003805 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003806 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003807 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303808 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003809 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303810 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3811 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3812 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3813 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303814 ret = -EINVAL;
3815 goto exit;
3816 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303817 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303818 ret = -errno;
3819 }
3820 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303821 /* bytes read is always set to bytes for non compress usecases */
3822 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 }
3824
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003825 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 /*
3828 * Instead of writing zeroes here, we could trust the hardware
3829 * to always provide zeroes when muted.
3830 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303831 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3832 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833 memset(buffer, 0, bytes);
3834
3835exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303836 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303837 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003838 if (-ENETRESET == ret)
3839 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 pthread_mutex_unlock(&in->lock);
3842
3843 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303844 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303845 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303846 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303847 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303848 in->standby = true;
3849 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303850 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3851 bytes_read = bytes;
3852 memset(buffer, 0, bytes);
3853 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003855 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303856 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303857 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303859 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860}
3861
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003862static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863{
3864 return 0;
3865}
3866
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003867static int add_remove_audio_effect(const struct audio_stream *stream,
3868 effect_handle_t effect,
3869 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003871 struct stream_in *in = (struct stream_in *)stream;
3872 int status = 0;
3873 effect_descriptor_t desc;
3874
3875 status = (*effect)->get_descriptor(effect, &desc);
3876 if (status != 0)
3877 return status;
3878
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003879 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003880 pthread_mutex_lock(&in->dev->lock);
3881 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3882 in->enable_aec != enable &&
3883 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3884 in->enable_aec = enable;
3885 if (!in->standby)
3886 select_devices(in->dev, in->usecase);
3887 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003888 if (in->enable_ns != enable &&
3889 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3890 in->enable_ns = enable;
3891 if (!in->standby)
3892 select_devices(in->dev, in->usecase);
3893 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003894 pthread_mutex_unlock(&in->dev->lock);
3895 pthread_mutex_unlock(&in->lock);
3896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 return 0;
3898}
3899
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003900static int in_add_audio_effect(const struct audio_stream *stream,
3901 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902{
Eric Laurent994a6932013-07-17 11:51:42 -07003903 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003904 return add_remove_audio_effect(stream, effect, true);
3905}
3906
3907static int in_remove_audio_effect(const struct audio_stream *stream,
3908 effect_handle_t effect)
3909{
Eric Laurent994a6932013-07-17 11:51:42 -07003910 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003911 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912}
3913
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303914int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 audio_io_handle_t handle,
3916 audio_devices_t devices,
3917 audio_output_flags_t flags,
3918 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003919 struct audio_stream_out **stream_out,
3920 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003921{
3922 struct audio_device *adev = (struct audio_device *)dev;
3923 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303924 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003925 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303928
3929 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3930 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003931 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303932 return -EINVAL;
3933 }
3934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3936
Mingming Yin3a941d42016-02-17 18:08:05 -08003937 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3938 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303939 devices, flags, &out->stream);
3940
3941
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003942 if (!out) {
3943 return -ENOMEM;
3944 }
3945
Haynes Mathew George204045b2015-02-25 20:32:03 -08003946 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003947 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003948 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950 if (devices == AUDIO_DEVICE_NONE)
3951 devices = AUDIO_DEVICE_OUT_SPEAKER;
3952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953 out->flags = flags;
3954 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003955 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003956 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003957 out->sample_rate = config->sample_rate;
3958 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3959 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003960 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003961 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003962 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303963 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964
Mingming Yin3a941d42016-02-17 18:08:05 -08003965 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3966 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3967 pthread_mutex_lock(&adev->lock);
3968 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3969 ret = read_hdmi_sink_caps(out);
3970 pthread_mutex_unlock(&adev->lock);
3971 if (ret != 0) {
3972 if (ret == -ENOSYS) {
3973 /* ignore and go with default */
3974 ret = 0;
3975 } else {
3976 ALOGE("error reading hdmi sink caps");
3977 goto error_open;
3978 }
3979 }
3980 }
3981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303983 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003984 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003985 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003986 ret = voice_extn_compress_voip_open_output_stream(out);
3987 if (ret != 0) {
3988 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3989 __func__, ret);
3990 goto error_open;
3991 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003992 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05303993 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003994
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3996 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3997 ALOGE("%s: Unsupported Offload information", __func__);
3998 ret = -EINVAL;
3999 goto error_open;
4000 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004001
Mingming Yin3a941d42016-02-17 18:08:05 -08004002 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004003 if(config->offload_info.format == 0)
4004 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004005 if (config->offload_info.sample_rate == 0)
4006 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004007 }
4008
Mingming Yin90310102013-11-13 16:57:00 -08004009 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304010 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004011 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004012 ret = -EINVAL;
4013 goto error_open;
4014 }
4015
4016 out->compr_config.codec = (struct snd_codec *)
4017 calloc(1, sizeof(struct snd_codec));
4018
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004019 if (!out->compr_config.codec) {
4020 ret = -ENOMEM;
4021 goto error_open;
4022 }
4023
Dhananjay Kumarac341582017-02-23 23:42:25 +05304024 out->stream.pause = out_pause;
4025 out->stream.resume = out_resume;
4026 out->stream.flush = out_flush;
4027 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004028 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004029 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304030 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004031 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304032 } else {
4033 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4034 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004035 }
vivek mehta446c3962015-09-14 10:57:35 -07004036
4037 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004038 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4039 config->format == 0 && config->sample_rate == 0 &&
4040 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004041 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004042 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4043 } else {
4044 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4045 ret = -EEXIST;
4046 goto error_open;
4047 }
vivek mehta446c3962015-09-14 10:57:35 -07004048 }
4049
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004050 if (config->offload_info.channel_mask)
4051 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004052 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004053 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004054 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004055 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304056 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004057 ret = -EINVAL;
4058 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004059 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004060
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004061 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004062 out->sample_rate = config->offload_info.sample_rate;
4063
Mingming Yin3ee55c62014-08-04 14:23:35 -07004064 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004065
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304066 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4067 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4068 audio_extn_dolby_send_ddp_endp_params(adev);
4069 audio_extn_dolby_set_dmid(adev);
4070 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004071
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004073 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004074 out->compr_config.codec->bit_rate =
4075 config->offload_info.bit_rate;
4076 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304077 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004078 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304079 /* Update bit width only for non passthrough usecases.
4080 * For passthrough usecases, the output will always be opened @16 bit
4081 */
4082 if (!audio_extn_passthru_is_passthrough_stream(out))
4083 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004084 /*TODO: Do we need to change it for passthrough */
4085 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004086
Manish Dewangana6fc5442015-08-24 20:30:31 +05304087 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4088 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304089 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304090 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304091 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4092 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304093
4094 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4095 AUDIO_FORMAT_PCM) {
4096
4097 /*Based on platform support, configure appropriate alsa format for corresponding
4098 *hal input format.
4099 */
4100 out->compr_config.codec->format = hal_format_to_alsa(
4101 config->offload_info.format);
4102
Ashish Jain83a6cc22016-06-28 14:34:17 +05304103 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304104 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304105 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304106
Dhananjay Kumarac341582017-02-23 23:42:25 +05304107 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304108 *hal input format and alsa format might differ based on platform support.
4109 */
4110 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304111 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304112
4113 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4114
4115 /* Check if alsa session is configured with the same format as HAL input format,
4116 * if not then derive correct fragment size needed to accomodate the
4117 * conversion of HAL input format to alsa format.
4118 */
4119 audio_extn_utils_update_direct_pcm_fragment_size(out);
4120
4121 /*if hal input and output fragment size is different this indicates HAL input format is
4122 *not same as the alsa format
4123 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304124 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304125 /*Allocate a buffer to convert input data to the alsa configured format.
4126 *size of convert buffer is equal to the size required to hold one fragment size
4127 *worth of pcm data, this is because flinger does not write more than fragment_size
4128 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304129 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4130 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304131 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4132 ret = -ENOMEM;
4133 goto error_open;
4134 }
4135 }
4136 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4137 out->compr_config.fragment_size =
4138 audio_extn_passthru_get_buffer_size(&config->offload_info);
4139 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4140 } else {
4141 out->compr_config.fragment_size =
4142 platform_get_compress_offload_buffer_size(&config->offload_info);
4143 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4144 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004145
Amit Shekhar6f461b12014-08-01 14:52:58 -07004146 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304147 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004148
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304149 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4150 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4151 }
4152
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004153 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4154 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004155
Manish Dewangan69426c82017-01-30 17:35:36 +05304156 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4157 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4158 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4159 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4160 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4161 } else {
4162 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4163 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004164
Manish Dewangan27346042017-03-01 12:56:12 +05304165 memset(&out->render_window, 0,
4166 sizeof(struct audio_out_render_window_param));
4167
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004168 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304169 out->send_next_track_params = false;
4170 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004171 out->offload_state = OFFLOAD_STATE_IDLE;
4172 out->playback_started = 0;
4173
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004174 audio_extn_dts_create_state_notifier_node(out->usecase);
4175
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004176 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4177 __func__, config->offload_info.version,
4178 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304179
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304180 /* Check if DSD audio format is supported in codec
4181 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304182 */
4183
4184 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304185 (!platform_check_codec_dsd_support(adev->platform) ||
4186 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304187 ret = -EINVAL;
4188 goto error_open;
4189 }
4190
Ashish Jain5106d362016-05-11 19:23:33 +05304191 /* Disable gapless if any of the following is true
4192 * passthrough playback
4193 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304194 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304195 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304196 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304197 (config->format == AUDIO_FORMAT_DSD) ||
4198 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304199 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304200 check_and_set_gapless_mode(adev, false);
4201 } else
4202 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004203
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304204 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004205 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4206 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304207 if (config->format == AUDIO_FORMAT_DSD) {
4208 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4209 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4210 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004211
4212 create_offload_callback_thread(out);
4213
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004214 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304215 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004216 if (ret != 0) {
4217 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4218 __func__, ret);
4219 goto error_open;
4220 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004221 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4222 if (config->sample_rate == 0)
4223 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4224 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4225 config->sample_rate != 8000) {
4226 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4227 ret = -EINVAL;
4228 goto error_open;
4229 }
4230 out->sample_rate = config->sample_rate;
4231 out->config.rate = config->sample_rate;
4232 if (config->format == AUDIO_FORMAT_DEFAULT)
4233 config->format = AUDIO_FORMAT_PCM_16_BIT;
4234 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4235 config->format = AUDIO_FORMAT_PCM_16_BIT;
4236 ret = -EINVAL;
4237 goto error_open;
4238 }
4239 out->format = config->format;
4240 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4241 out->config = pcm_config_afe_proxy_playback;
4242 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004243 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304244 unsigned int channels = 0;
4245 /*Update config params to default if not set by the caller*/
4246 if (config->sample_rate == 0)
4247 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4248 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4249 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4250 if (config->format == AUDIO_FORMAT_DEFAULT)
4251 config->format = AUDIO_FORMAT_PCM_16_BIT;
4252
4253 channels = audio_channel_count_from_out_mask(out->channel_mask);
4254
Ashish Jain83a6cc22016-06-28 14:34:17 +05304255 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4256 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004257 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4258 out->flags);
4259 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304260 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4261 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4262 out->config = pcm_config_low_latency;
4263 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4264 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4265 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304266 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4267 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4268 if (out->config.period_size <= 0) {
4269 ALOGE("Invalid configuration period size is not valid");
4270 ret = -EINVAL;
4271 goto error_open;
4272 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304273 } else {
4274 /* primary path is the default path selected if no other outputs are available/suitable */
4275 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4276 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4277 }
4278 out->hal_ip_format = format = out->format;
4279 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4280 out->hal_op_format = pcm_format_to_hal(out->config.format);
4281 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4282 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004283 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304284 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304285 if (out->hal_ip_format != out->hal_op_format) {
4286 uint32_t buffer_size = out->config.period_size *
4287 format_to_bitwidth_table[out->hal_op_format] *
4288 out->config.channels;
4289 out->convert_buffer = calloc(1, buffer_size);
4290 if (out->convert_buffer == NULL){
4291 ALOGE("Allocation failed for convert buffer for size %d",
4292 out->compr_config.fragment_size);
4293 ret = -ENOMEM;
4294 goto error_open;
4295 }
4296 ALOGD("Convert buffer allocated of size %d", buffer_size);
4297 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298 }
4299
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004300 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4301 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304302
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004303 /* TODO remove this hardcoding and check why width is zero*/
4304 if (out->bit_width == 0)
4305 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304306 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004307 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304308 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304309 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304310 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004311 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4312 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4313 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004314 if(adev->primary_output == NULL)
4315 adev->primary_output = out;
4316 else {
4317 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004318 ret = -EEXIST;
4319 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004320 }
4321 }
4322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323 /* Check if this usecase is already existing */
4324 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004325 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4326 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004329 ret = -EEXIST;
4330 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004331 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 pthread_mutex_unlock(&adev->lock);
4334
4335 out->stream.common.get_sample_rate = out_get_sample_rate;
4336 out->stream.common.set_sample_rate = out_set_sample_rate;
4337 out->stream.common.get_buffer_size = out_get_buffer_size;
4338 out->stream.common.get_channels = out_get_channels;
4339 out->stream.common.get_format = out_get_format;
4340 out->stream.common.set_format = out_set_format;
4341 out->stream.common.standby = out_standby;
4342 out->stream.common.dump = out_dump;
4343 out->stream.common.set_parameters = out_set_parameters;
4344 out->stream.common.get_parameters = out_get_parameters;
4345 out->stream.common.add_audio_effect = out_add_audio_effect;
4346 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4347 out->stream.get_latency = out_get_latency;
4348 out->stream.set_volume = out_set_volume;
4349 out->stream.write = out_write;
4350 out->stream.get_render_position = out_get_render_position;
4351 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004352 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004354 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004356 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004357 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358
4359 config->format = out->stream.common.get_format(&out->stream.common);
4360 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4361 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4362
4363 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304364 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004365 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004366
4367 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4368 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4369 popcount(out->channel_mask), out->playback_started);
4370
Eric Laurent994a6932013-07-17 11:51:42 -07004371 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004373
4374error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304375 if (out->convert_buffer)
4376 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004377 free(out);
4378 *stream_out = NULL;
4379 ALOGD("%s: exit: ret %d", __func__, ret);
4380 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381}
4382
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304383void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384 struct audio_stream_out *stream)
4385{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004386 struct stream_out *out = (struct stream_out *)stream;
4387 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004388 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004389
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304390 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4391
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004392 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304393 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004394 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304395 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004396 if(ret != 0)
4397 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4398 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004399 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004400 out_standby(&stream->common);
4401
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004402 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004403 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004404 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004405 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004406 if (out->compr_config.codec != NULL)
4407 free(out->compr_config.codec);
4408 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004409
Ashish Jain83a6cc22016-06-28 14:34:17 +05304410 if (out->convert_buffer != NULL) {
4411 free(out->convert_buffer);
4412 out->convert_buffer = NULL;
4413 }
4414
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004415 if (adev->voice_tx_output == out)
4416 adev->voice_tx_output = NULL;
4417
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304418 if (adev->primary_output == out)
4419 adev->primary_output = NULL;
4420
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004421 pthread_cond_destroy(&out->cond);
4422 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004424 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425}
4426
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004427static void close_compress_sessions(struct audio_device *adev)
4428{
Mingming Yin7b762e72015-03-04 13:47:32 -08004429 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304430 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004431 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004432 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304433
4434 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004435 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304436 if (is_offload_usecase(usecase->id)) {
4437 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004438 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4439 out = usecase->stream.out;
4440 pthread_mutex_unlock(&adev->lock);
4441 out_standby(&out->stream.common);
4442 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004443 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004444 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304445 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004446 }
4447 pthread_mutex_unlock(&adev->lock);
4448}
4449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4451{
4452 struct audio_device *adev = (struct audio_device *)dev;
4453 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004455 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004456 int ret;
4457 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004459 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004460 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304462 if (!parms)
4463 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004464 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4465 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304466 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304467 if (strstr(snd_card_status, "OFFLINE")) {
4468 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304469 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004470 //close compress sessions on OFFLINE status
4471 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304472 } else if (strstr(snd_card_status, "ONLINE")) {
4473 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304474 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004475 //send dts hpx license if enabled
4476 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304477 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304478 }
4479
4480 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004481 status = voice_set_parameters(adev, parms);
4482 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004483 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004485 status = platform_set_parameters(adev->platform, parms);
4486 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004487 goto done;
4488
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004489 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4490 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004491 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4493 adev->bluetooth_nrec = true;
4494 else
4495 adev->bluetooth_nrec = false;
4496 }
4497
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004498 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4499 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4501 adev->screen_off = false;
4502 else
4503 adev->screen_off = true;
4504 }
4505
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004506 ret = str_parms_get_int(parms, "rotation", &val);
4507 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004508 bool reverse_speakers = false;
4509 switch(val) {
4510 // FIXME: note that the code below assumes that the speakers are in the correct placement
4511 // relative to the user when the device is rotated 90deg from its default rotation. This
4512 // assumption is device-specific, not platform-specific like this code.
4513 case 270:
4514 reverse_speakers = true;
4515 break;
4516 case 0:
4517 case 90:
4518 case 180:
4519 break;
4520 default:
4521 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004522 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004523 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004524 if (status == 0) {
4525 if (adev->speaker_lr_swap != reverse_speakers) {
4526 adev->speaker_lr_swap = reverse_speakers;
4527 // only update the selected device if there is active pcm playback
4528 struct audio_usecase *usecase;
4529 struct listnode *node;
4530 list_for_each(node, &adev->usecase_list) {
4531 usecase = node_to_item(node, struct audio_usecase, list);
4532 if (usecase->type == PCM_PLAYBACK) {
4533 select_devices(adev, usecase->id);
4534 break;
4535 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004536 }
4537 }
4538 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004539 }
4540
Mingming Yin514a8bc2014-07-29 15:22:21 -07004541 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4542 if (ret >= 0) {
4543 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4544 adev->bt_wb_speech_enabled = true;
4545 else
4546 adev->bt_wb_speech_enabled = false;
4547 }
4548
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004549 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4550 if (ret >= 0) {
4551 val = atoi(value);
4552 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004553 ALOGV("cache new ext disp type and edid");
4554 ret = platform_get_ext_disp_type(adev->platform);
4555 if (ret < 0) {
4556 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004557 status = ret;
4558 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004559 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004560 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004561 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004562 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004563 /*
4564 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4565 * Per AudioPolicyManager, USB device is higher priority than WFD.
4566 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4567 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4568 * starting voice call on USB
4569 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004570 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4571 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004572 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4573 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004574 }
vivek mehta344576a2016-04-12 18:56:03 -07004575 ALOGV("detected USB connect .. disable proxy");
4576 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004577 }
4578 }
4579
4580 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4581 if (ret >= 0) {
4582 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004583 /*
4584 * The HDMI / Displayport disconnect handling has been moved to
4585 * audio extension to ensure that its parameters are not
4586 * invalidated prior to updating sysfs of the disconnect event
4587 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4588 */
4589 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004590 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004591 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4592 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304593 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4594 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004595 }
vivek mehta344576a2016-04-12 18:56:03 -07004596 ALOGV("detected USB disconnect .. enable proxy");
4597 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004598 }
4599 }
4600
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304601 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4602 if (ret >= 0) {
4603 struct audio_usecase *usecase;
4604 struct listnode *node;
4605 list_for_each(node, &adev->usecase_list) {
4606 usecase = node_to_item(node, struct audio_usecase, list);
4607 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004608 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304609 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304610 lock_output_stream(usecase->stream.out);
4611 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304612 //force device switch to re configure encoder
4613 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304614 audio_extn_a2dp_set_handoff_mode(false);
4615 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304616 break;
4617 }
4618 }
4619 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004620
4621 //handle vr audio setparam
4622 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4623 value, sizeof(value));
4624 if (ret >= 0) {
4625 ALOGI("Setting vr mode to be %s", value);
4626 if (!strncmp(value, "true", 4)) {
4627 adev->vr_audio_mode_enabled = true;
4628 ALOGI("Setting vr mode to true");
4629 } else if (!strncmp(value, "false", 5)) {
4630 adev->vr_audio_mode_enabled = false;
4631 ALOGI("Setting vr mode to false");
4632 } else {
4633 ALOGI("wrong vr mode set");
4634 }
4635 }
4636
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304637 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004638done:
4639 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004640 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304641error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004642 ALOGV("%s: exit with code(%d)", __func__, status);
4643 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644}
4645
4646static char* adev_get_parameters(const struct audio_hw_device *dev,
4647 const char *keys)
4648{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004649 struct audio_device *adev = (struct audio_device *)dev;
4650 struct str_parms *reply = str_parms_create();
4651 struct str_parms *query = str_parms_create_str(keys);
4652 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304653 char value[256] = {0};
4654 int ret = 0;
4655
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004656 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004657 if (reply) {
4658 str_parms_destroy(reply);
4659 }
4660 if (query) {
4661 str_parms_destroy(query);
4662 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004663 ALOGE("adev_get_parameters: failed to create query or reply");
4664 return NULL;
4665 }
4666
Naresh Tannirud7205b62014-06-20 02:54:48 +05304667 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4668 sizeof(value));
4669 if (ret >=0) {
4670 int val = 1;
4671 pthread_mutex_lock(&adev->snd_card_status.lock);
4672 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4673 val = 0;
4674 pthread_mutex_unlock(&adev->snd_card_status.lock);
4675 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4676 goto exit;
4677 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004678 //handle vr audio getparam
4679
4680 ret = str_parms_get_str(query,
4681 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4682 value, sizeof(value));
4683
4684 if (ret >= 0) {
4685 bool vr_audio_enabled = false;
4686 pthread_mutex_lock(&adev->lock);
4687 vr_audio_enabled = adev->vr_audio_mode_enabled;
4688 pthread_mutex_unlock(&adev->lock);
4689
4690 ALOGI("getting vr mode to %d", vr_audio_enabled);
4691
4692 if (vr_audio_enabled) {
4693 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4694 "true");
4695 goto exit;
4696 } else {
4697 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4698 "false");
4699 goto exit;
4700 }
4701 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004702
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004703 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004704 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004705 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004706 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304707 pthread_mutex_unlock(&adev->lock);
4708
Naresh Tannirud7205b62014-06-20 02:54:48 +05304709exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004710 str = str_parms_to_str(reply);
4711 str_parms_destroy(query);
4712 str_parms_destroy(reply);
4713
4714 ALOGV("%s: exit: returns - %s", __func__, str);
4715 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716}
4717
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004718static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719{
4720 return 0;
4721}
4722
4723static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4724{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004725 int ret;
4726 struct audio_device *adev = (struct audio_device *)dev;
4727 pthread_mutex_lock(&adev->lock);
4728 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004729 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004730 pthread_mutex_unlock(&adev->lock);
4731 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004732}
4733
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004734static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4735 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004736{
4737 return -ENOSYS;
4738}
4739
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004740static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4741 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742{
4743 return -ENOSYS;
4744}
4745
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004746static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4747 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748{
4749 return -ENOSYS;
4750}
4751
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004752static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4753 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004754{
4755 return -ENOSYS;
4756}
4757
4758static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4759{
4760 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762 pthread_mutex_lock(&adev->lock);
4763 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004764 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004766 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004767 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004768 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004769 adev->current_call_output = NULL;
4770 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 }
4772 pthread_mutex_unlock(&adev->lock);
4773 return 0;
4774}
4775
4776static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4777{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004778 int ret;
4779
4780 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004781 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004782 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4783 pthread_mutex_unlock(&adev->lock);
4784
4785 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004786}
4787
4788static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4789{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004790 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791 return 0;
4792}
4793
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004794static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795 const struct audio_config *config)
4796{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004797 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004799 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4800 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801}
4802
4803static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004804 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805 audio_devices_t devices,
4806 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004807 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304808 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004809 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004810 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004811{
4812 struct audio_device *adev = (struct audio_device *)dev;
4813 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004814 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004815 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004816 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304817 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304820 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4821 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304823 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004824
4825 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004826
4827 if (!in) {
4828 ALOGE("failed to allocate input stream");
4829 return -ENOMEM;
4830 }
4831
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304832 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304833 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4834 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004835 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004836 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004838 in->stream.common.get_sample_rate = in_get_sample_rate;
4839 in->stream.common.set_sample_rate = in_set_sample_rate;
4840 in->stream.common.get_buffer_size = in_get_buffer_size;
4841 in->stream.common.get_channels = in_get_channels;
4842 in->stream.common.get_format = in_get_format;
4843 in->stream.common.set_format = in_set_format;
4844 in->stream.common.standby = in_standby;
4845 in->stream.common.dump = in_dump;
4846 in->stream.common.set_parameters = in_set_parameters;
4847 in->stream.common.get_parameters = in_get_parameters;
4848 in->stream.common.add_audio_effect = in_add_audio_effect;
4849 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4850 in->stream.set_gain = in_set_gain;
4851 in->stream.read = in_read;
4852 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4853
4854 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004855 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857 in->standby = 1;
4858 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004859 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004860 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304862 in->usecase = USECASE_AUDIO_RECORD;
4863 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4864 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4865 is_low_latency = true;
4866#if LOW_LATENCY_CAPTURE_USE_CASE
4867 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4868#endif
4869 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4870 }
4871
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004872 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004873 if (in->realtime) {
4874 in->config = pcm_config_audio_capture_rt;
4875 in->sample_rate = in->config.rate;
4876 in->af_period_multiplier = af_period_multiplier;
4877 } else {
4878 in->config = pcm_config_audio_capture;
4879 in->config.rate = config->sample_rate;
4880 in->sample_rate = config->sample_rate;
4881 in->af_period_multiplier = 1;
4882 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304883 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304885 /* restrict 24 bit capture for unprocessed source only
4886 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4887 */
4888 if (config->format == AUDIO_FORMAT_DEFAULT) {
4889 config->format = AUDIO_FORMAT_PCM_16_BIT;
4890 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4891 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4892 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4893 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4894 bool ret_error = false;
4895 in->bit_width = 24;
4896 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4897 from HAL is 24_packed and 8_24
4898 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4899 24_packed return error indicating supported format is 24_packed
4900 *> In case of any other source requesting 24 bit or float return error
4901 indicating format supported is 16 bit only.
4902
4903 on error flinger will retry with supported format passed
4904 */
4905 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4906 (source != AUDIO_SOURCE_CAMCORDER)) {
4907 config->format = AUDIO_FORMAT_PCM_16_BIT;
4908 if (config->sample_rate > 48000)
4909 config->sample_rate = 48000;
4910 ret_error = true;
4911 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4912 in->config.format = PCM_FORMAT_S24_3LE;
4913 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4914 in->config.format = PCM_FORMAT_S24_LE;
4915 } else {
4916 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4917 ret_error = true;
4918 }
4919
4920 if (ret_error) {
4921 ret = -EINVAL;
4922 goto err_open;
4923 }
4924 }
4925
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304926 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304927 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4928 (adev->mode != AUDIO_MODE_IN_CALL)) {
4929 ret = -EINVAL;
4930 goto err_open;
4931 }
4932
4933 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4934 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004935 if (config->sample_rate == 0)
4936 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4937 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4938 config->sample_rate != 8000) {
4939 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4940 ret = -EINVAL;
4941 goto err_open;
4942 }
4943 if (config->format == AUDIO_FORMAT_DEFAULT)
4944 config->format = AUDIO_FORMAT_PCM_16_BIT;
4945 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4946 config->format = AUDIO_FORMAT_PCM_16_BIT;
4947 ret = -EINVAL;
4948 goto err_open;
4949 }
4950
4951 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4952 in->config = pcm_config_afe_proxy_record;
4953 in->config.channels = channel_count;
4954 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304955 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304956 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4957 in, config, &channel_mask_updated)) {
4958 if (channel_mask_updated == true) {
4959 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4960 __func__, config->channel_mask);
4961 ret = -EINVAL;
4962 goto err_open;
4963 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304964 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004965 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004966 audio_extn_compr_cap_format_supported(config->format) &&
4967 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004968 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304969 } else if (audio_extn_cin_applicable_stream(in)) {
4970 ret = audio_extn_cin_configure_input_stream(in);
4971 if (ret)
4972 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004973 } else {
4974 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004975 if (!in->realtime) {
4976 in->format = config->format;
4977 frame_size = audio_stream_in_frame_size(&in->stream);
4978 buffer_size = get_input_buffer_size(config->sample_rate,
4979 config->format,
4980 channel_count,
4981 is_low_latency);
4982 in->config.period_size = buffer_size / frame_size;
4983 }
4984
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004985 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004986 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004987 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004988 (in->config.rate == 8000 || in->config.rate == 16000 ||
4989 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004990 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4991 voice_extn_compress_voip_open_input_stream(in);
4992 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004993 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304995 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4996 &adev->streams_input_cfg_list,
4997 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304998 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304999
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005000 /* This stream could be for sound trigger lab,
5001 get sound trigger pcm if present */
5002 audio_extn_sound_trigger_check_and_get_session(in);
5003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005005 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005006 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005007
5008err_open:
5009 free(in);
5010 *stream_in = NULL;
5011 return ret;
5012}
5013
5014static void adev_close_input_stream(struct audio_hw_device *dev,
5015 struct audio_stream_in *stream)
5016{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005017 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005018 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005019 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305020
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305021 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005022
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305023 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005024 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305025
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005026 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305027 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005028 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305029 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005030 if (ret != 0)
5031 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5032 __func__, ret);
5033 } else
5034 in_standby(&stream->common);
5035
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005036 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005037 audio_extn_ssr_deinit();
5038 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305040 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005041 audio_extn_compr_cap_format_supported(in->config.format))
5042 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305043
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305044 if (audio_extn_cin_attached_usecase(in->usecase))
5045 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005046
Mingming Yinfd7607b2016-01-22 12:48:44 -08005047 if (in->is_st_session) {
5048 ALOGV("%s: sound trigger pcm stop lab", __func__);
5049 audio_extn_sound_trigger_stop_lab(in);
5050 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005051 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005052 return;
5053}
5054
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005055static int adev_dump(const audio_hw_device_t *device __unused,
5056 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005057{
5058 return 0;
5059}
5060
5061static int adev_close(hw_device_t *device)
5062{
5063 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005064
5065 if (!adev)
5066 return 0;
5067
5068 pthread_mutex_lock(&adev_init_lock);
5069
5070 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005071 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005072 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305073 audio_extn_utils_release_streams_cfg_lists(
5074 &adev->streams_output_cfg_list,
5075 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305076 if (audio_extn_qaf_is_enabled())
5077 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005078 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005079 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005080 free(adev->snd_dev_ref_cnt);
5081 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005082 if (adev->adm_deinit)
5083 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305084 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005085 free(device);
5086 adev = NULL;
5087 }
5088 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005090 return 0;
5091}
5092
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005093/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5094 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5095 * just that it _might_ work.
5096 */
5097static int period_size_is_plausible_for_low_latency(int period_size)
5098{
5099 switch (period_size) {
5100 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005101 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005102 case 240:
5103 case 320:
5104 case 480:
5105 return 1;
5106 default:
5107 return 0;
5108 }
5109}
5110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111static int adev_open(const hw_module_t *module, const char *name,
5112 hw_device_t **device)
5113{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305114 int ret;
5115
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005116 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005117 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5118
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005119 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005120 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005121 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005122 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005123 ALOGD("%s: returning existing instance of adev", __func__);
5124 ALOGD("%s: exit", __func__);
5125 pthread_mutex_unlock(&adev_init_lock);
5126 return 0;
5127 }
5128
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129 adev = calloc(1, sizeof(struct audio_device));
5130
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005131 if (!adev) {
5132 pthread_mutex_unlock(&adev_init_lock);
5133 return -ENOMEM;
5134 }
5135
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005136 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005138 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5139 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5140 adev->device.common.module = (struct hw_module_t *)module;
5141 adev->device.common.close = adev_close;
5142
5143 adev->device.init_check = adev_init_check;
5144 adev->device.set_voice_volume = adev_set_voice_volume;
5145 adev->device.set_master_volume = adev_set_master_volume;
5146 adev->device.get_master_volume = adev_get_master_volume;
5147 adev->device.set_master_mute = adev_set_master_mute;
5148 adev->device.get_master_mute = adev_get_master_mute;
5149 adev->device.set_mode = adev_set_mode;
5150 adev->device.set_mic_mute = adev_set_mic_mute;
5151 adev->device.get_mic_mute = adev_get_mic_mute;
5152 adev->device.set_parameters = adev_set_parameters;
5153 adev->device.get_parameters = adev_get_parameters;
5154 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5155 adev->device.open_output_stream = adev_open_output_stream;
5156 adev->device.close_output_stream = adev_close_output_stream;
5157 adev->device.open_input_stream = adev_open_input_stream;
5158 adev->device.close_input_stream = adev_close_input_stream;
5159 adev->device.dump = adev_dump;
5160
5161 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005162 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005163 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005164 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005165 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005167 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005168 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005169 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005170 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005171 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005172 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005173 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005174 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305175 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305176 adev->perf_lock_opts[0] = 0x101;
5177 adev->perf_lock_opts[1] = 0x20E;
5178 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305179
5180 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5181 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005182 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005183 adev->platform = platform_init(adev);
5184 if (!adev->platform) {
5185 free(adev->snd_dev_ref_cnt);
5186 free(adev);
5187 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5188 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005189 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305190 pthread_mutex_destroy(&adev->lock);
5191 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005192 return -EINVAL;
5193 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005194
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305195 if (audio_extn_qaf_is_enabled()) {
5196 ret = audio_extn_qaf_init(adev);
5197 if (ret < 0) {
5198 free(adev);
5199 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5200 *device = NULL;
5201 pthread_mutex_unlock(&adev_init_lock);
5202 pthread_mutex_destroy(&adev->lock);
5203 return ret;
5204 }
5205
5206 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5207 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5208 }
5209
Naresh Tanniru4c630392014-05-12 01:05:52 +05305210 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5211
Eric Laurentc4aef752013-09-12 17:45:53 -07005212 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5213 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5214 if (adev->visualizer_lib == NULL) {
5215 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5216 } else {
5217 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5218 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005219 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005220 "visualizer_hal_start_output");
5221 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005222 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005223 "visualizer_hal_stop_output");
5224 }
5225 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305226 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005227 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005228 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005229 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005230
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005231 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5232 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5233 if (adev->offload_effects_lib == NULL) {
5234 ALOGE("%s: DLOPEN failed for %s", __func__,
5235 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5236 } else {
5237 ALOGV("%s: DLOPEN successful for %s", __func__,
5238 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5239 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305240 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005241 "offload_effects_bundle_hal_start_output");
5242 adev->offload_effects_stop_output =
5243 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5244 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005245 adev->offload_effects_set_hpx_state =
5246 (int (*)(bool))dlsym(adev->offload_effects_lib,
5247 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305248 adev->offload_effects_get_parameters =
5249 (void (*)(struct str_parms *, struct str_parms *))
5250 dlsym(adev->offload_effects_lib,
5251 "offload_effects_bundle_get_parameters");
5252 adev->offload_effects_set_parameters =
5253 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5254 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005255 }
5256 }
5257
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005258 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5259 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5260 if (adev->adm_lib == NULL) {
5261 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5262 } else {
5263 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5264 adev->adm_init = (adm_init_t)
5265 dlsym(adev->adm_lib, "adm_init");
5266 adev->adm_deinit = (adm_deinit_t)
5267 dlsym(adev->adm_lib, "adm_deinit");
5268 adev->adm_register_input_stream = (adm_register_input_stream_t)
5269 dlsym(adev->adm_lib, "adm_register_input_stream");
5270 adev->adm_register_output_stream = (adm_register_output_stream_t)
5271 dlsym(adev->adm_lib, "adm_register_output_stream");
5272 adev->adm_deregister_stream = (adm_deregister_stream_t)
5273 dlsym(adev->adm_lib, "adm_deregister_stream");
5274 adev->adm_request_focus = (adm_request_focus_t)
5275 dlsym(adev->adm_lib, "adm_request_focus");
5276 adev->adm_abandon_focus = (adm_abandon_focus_t)
5277 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005278 adev->adm_set_config = (adm_set_config_t)
5279 dlsym(adev->adm_lib, "adm_set_config");
5280 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5281 dlsym(adev->adm_lib, "adm_request_focus_v2");
5282 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5283 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5284 adev->adm_on_routing_change = (adm_on_routing_change_t)
5285 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005286 }
5287 }
5288
Mingming Yin514a8bc2014-07-29 15:22:21 -07005289 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005290 //initialize this to false for now,
5291 //this will be set to true through set param
5292 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005293
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005294 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295 *device = &adev->device.common;
5296
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305297 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5298 &adev->streams_output_cfg_list,
5299 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005300
Kiran Kandi910e1862013-10-29 13:29:42 -07005301 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005302
5303 char value[PROPERTY_VALUE_MAX];
5304 int trial;
5305 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5306 trial = atoi(value);
5307 if (period_size_is_plausible_for_low_latency(trial)) {
5308 pcm_config_low_latency.period_size = trial;
5309 pcm_config_low_latency.start_threshold = trial / 4;
5310 pcm_config_low_latency.avail_min = trial / 4;
5311 configured_low_latency_capture_period_size = trial;
5312 }
5313 }
5314 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5315 trial = atoi(value);
5316 if (period_size_is_plausible_for_low_latency(trial)) {
5317 configured_low_latency_capture_period_size = trial;
5318 }
5319 }
5320
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005321 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5322 af_period_multiplier = atoi(value);
5323 if (af_period_multiplier < 0)
5324 af_period_multiplier = 2;
5325 else if (af_period_multiplier > 4)
5326 af_period_multiplier = 4;
5327
5328 ALOGV("new period_multiplier = %d", af_period_multiplier);
5329 }
5330
vivek mehta446c3962015-09-14 10:57:35 -07005331 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005332 pthread_mutex_unlock(&adev_init_lock);
5333
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005334 if (adev->adm_init)
5335 adev->adm_data = adev->adm_init();
5336
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305337 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305338 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005339 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005340 return 0;
5341}
5342
5343static struct hw_module_methods_t hal_module_methods = {
5344 .open = adev_open,
5345};
5346
5347struct audio_module HAL_MODULE_INFO_SYM = {
5348 .common = {
5349 .tag = HARDWARE_MODULE_TAG,
5350 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5351 .hal_api_version = HARDWARE_HAL_API_VERSION,
5352 .id = AUDIO_HARDWARE_MODULE_ID,
5353 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005354 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005355 .methods = &hal_module_methods,
5356 },
5357};