blob: 15ee7b4b5649c6932a3db0a58021a4a24068be32 [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),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700296 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800297 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
298 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
299};
300
301//list of all supported sample rates by HDMI specification.
302static const int out_hdmi_sample_rates[] = {
303 32000, 44100, 48000, 88200, 96000, 176400, 192000,
304};
305
306static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
307 STRING_TO_ENUM(32000),
308 STRING_TO_ENUM(44100),
309 STRING_TO_ENUM(48000),
310 STRING_TO_ENUM(88200),
311 STRING_TO_ENUM(96000),
312 STRING_TO_ENUM(176400),
313 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700314};
315
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700316static struct audio_device *adev = NULL;
317static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700318static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700319//cache last MBDRC cal step level
320static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700321
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700322static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
323 int flags __unused)
324{
325 int dir = 0;
326 switch (uc_id) {
327 case USECASE_AUDIO_RECORD_LOW_LATENCY:
328 dir = 1;
329 case USECASE_AUDIO_PLAYBACK_ULL:
330 break;
331 default:
332 return false;
333 }
334
335 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
336 PCM_PLAYBACK : PCM_CAPTURE);
337 if (adev->adm_is_noirq_avail)
338 return adev->adm_is_noirq_avail(adev->adm_data,
339 adev->snd_card, dev_id, dir);
340 return false;
341}
342
343static void register_out_stream(struct stream_out *out)
344{
345 struct audio_device *adev = out->dev;
346 if (is_offload_usecase(out->usecase) ||
347 !adev->adm_register_output_stream)
348 return;
349
350 // register stream first for backward compatibility
351 adev->adm_register_output_stream(adev->adm_data,
352 out->handle,
353 out->flags);
354
355 if (!adev->adm_set_config)
356 return;
357
358 if (out->realtime)
359 adev->adm_set_config(adev->adm_data,
360 out->handle,
361 out->pcm, &out->config);
362}
363
364static void register_in_stream(struct stream_in *in)
365{
366 struct audio_device *adev = in->dev;
367 if (!adev->adm_register_input_stream)
368 return;
369
370 adev->adm_register_input_stream(adev->adm_data,
371 in->capture_handle,
372 in->flags);
373
374 if (!adev->adm_set_config)
375 return;
376
377 if (in->realtime)
378 adev->adm_set_config(adev->adm_data,
379 in->capture_handle,
380 in->pcm,
381 &in->config);
382}
383
384static void request_out_focus(struct stream_out *out, long ns)
385{
386 struct audio_device *adev = out->dev;
387
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700388 if (adev->adm_request_focus_v2)
389 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
390 else if (adev->adm_request_focus)
391 adev->adm_request_focus(adev->adm_data, out->handle);
392}
393
394static void request_in_focus(struct stream_in *in, long ns)
395{
396 struct audio_device *adev = in->dev;
397
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700398 if (adev->adm_request_focus_v2)
399 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
400 else if (adev->adm_request_focus)
401 adev->adm_request_focus(adev->adm_data, in->capture_handle);
402}
403
404static void release_out_focus(struct stream_out *out)
405{
406 struct audio_device *adev = out->dev;
407
408 if (adev->adm_abandon_focus)
409 adev->adm_abandon_focus(adev->adm_data, out->handle);
410}
411
412static void release_in_focus(struct stream_in *in)
413{
414 struct audio_device *adev = in->dev;
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
417}
418
vivek mehtaa76401a2015-04-24 14:12:15 -0700419__attribute__ ((visibility ("default")))
420bool audio_hw_send_gain_dep_calibration(int level) {
421 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700422 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700423
424 pthread_mutex_lock(&adev_init_lock);
425
426 if (adev != NULL && adev->platform != NULL) {
427 pthread_mutex_lock(&adev->lock);
428 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700429
430 // if cal set fails, cache level info
431 // if cal set succeds, reset known last cal set
432 if (!ret_val)
433 last_known_cal_step = level;
434 else if (last_known_cal_step != -1)
435 last_known_cal_step = -1;
436
vivek mehtaa76401a2015-04-24 14:12:15 -0700437 pthread_mutex_unlock(&adev->lock);
438 } else {
439 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
440 }
441
442 pthread_mutex_unlock(&adev_init_lock);
443
444 return ret_val;
445}
446
Ashish Jain5106d362016-05-11 19:23:33 +0530447static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
448{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800449 bool gapless_enabled = false;
450 const char *mixer_ctl_name = "Compress Gapless Playback";
451 struct mixer_ctl *ctl;
452
453 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530454 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
455
456 /*Disable gapless if its AV playback*/
457 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800458
459 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
460 if (!ctl) {
461 ALOGE("%s: Could not get ctl for mixer cmd - %s",
462 __func__, mixer_ctl_name);
463 return -EINVAL;
464 }
465
466 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
467 ALOGE("%s: Could not set gapless mode %d",
468 __func__, gapless_enabled);
469 return -EINVAL;
470 }
471 return 0;
472}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700473
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700474__attribute__ ((visibility ("default")))
475int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
476 int table_size) {
477 int ret_val = 0;
478 ALOGV("%s: enter ... ", __func__);
479
480 pthread_mutex_lock(&adev_init_lock);
481 if (adev == NULL) {
482 ALOGW("%s: adev is NULL .... ", __func__);
483 goto done;
484 }
485
486 pthread_mutex_lock(&adev->lock);
487 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
488 pthread_mutex_unlock(&adev->lock);
489done:
490 pthread_mutex_unlock(&adev_init_lock);
491 ALOGV("%s: exit ... ", __func__);
492 return ret_val;
493}
494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700495static bool is_supported_format(audio_format_t format)
496{
Eric Laurent86e17132013-09-12 17:49:30 -0700497 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530498 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530499 format == AUDIO_FORMAT_AAC_LC ||
500 format == AUDIO_FORMAT_AAC_HE_V1 ||
501 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530502 format == AUDIO_FORMAT_AAC_ADTS_LC ||
503 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
504 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530505 format == AUDIO_FORMAT_AAC_LATM_LC ||
506 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
507 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530508 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
509 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530510 format == AUDIO_FORMAT_PCM_FLOAT ||
511 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700512 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530513 format == AUDIO_FORMAT_AC3 ||
514 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700515 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530516 format == AUDIO_FORMAT_DTS ||
517 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800518 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530519 format == AUDIO_FORMAT_ALAC ||
520 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530521 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530522 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800523 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530524 format == AUDIO_FORMAT_WMA_PRO ||
525 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800526 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700527
528 return false;
529}
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static inline bool is_mmap_usecase(audio_usecase_t uc_id)
532{
533 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
534 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
535}
536
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530537int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530538{
539 int snd_scard_state;
540
541 if (!adev)
542 return SND_CARD_STATE_OFFLINE;
543
544 pthread_mutex_lock(&adev->snd_card_status.lock);
545 snd_scard_state = adev->snd_card_status.state;
546 pthread_mutex_unlock(&adev->snd_card_status.lock);
547
548 return snd_scard_state;
549}
550
551static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
552{
553 if (!adev)
554 return -ENOSYS;
555
556 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700557 if (adev->snd_card_status.state != snd_scard_state) {
558 adev->snd_card_status.state = snd_scard_state;
559 platform_snd_card_update(adev->platform, snd_scard_state);
560 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530561 pthread_mutex_unlock(&adev->snd_card_status.lock);
562
563 return 0;
564}
565
Avinash Vaish71a8b972014-07-24 15:36:33 +0530566static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
567 struct audio_usecase *uc_info)
568{
569 struct listnode *node;
570 struct audio_usecase *usecase;
571
572 if (uc_info == NULL)
573 return -EINVAL;
574
575 /* Re-route all voice usecases on the shared backend other than the
576 specified usecase to new snd devices */
577 list_for_each(node, &adev->usecase_list) {
578 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800579 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530580 enable_audio_route(adev, usecase);
581 }
582 return 0;
583}
584
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530586{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530587 ALOGV("%s", __func__);
588 audio_route_apply_and_update_path(adev->audio_route,
589 "asrc-mode");
590 adev->asrc_mode_enabled = true;
591}
592
593static void disable_asrc_mode(struct audio_device *adev)
594{
595 ALOGV("%s", __func__);
596 audio_route_reset_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = false;
599}
600
601/*
602 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
603 * 44.1 or Native DSD backends are enabled for any of current use case.
604 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
605 * - Disable current mix path use case(Headphone backend) and re-enable it with
606 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
607 * e.g. Naitve DSD or Headphone 44.1 -> + 48
608 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530609static void check_and_set_asrc_mode(struct audio_device *adev,
610 struct audio_usecase *uc_info,
611 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530612{
613 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530614 int i, num_new_devices = 0;
615 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
616 /*
617 *Split snd device for new combo use case
618 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
619 */
620 if (platform_split_snd_device(adev->platform,
621 snd_device,
622 &num_new_devices,
623 split_new_snd_devices) == 0) {
624 for (i = 0; i < num_new_devices; i++)
625 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
626 } else {
627 int new_backend_idx = platform_get_backend_index(snd_device);
628 if (((new_backend_idx == HEADPHONE_BACKEND) ||
629 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
630 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
631 !adev->asrc_mode_enabled) {
632 struct listnode *node = NULL;
633 struct audio_usecase *uc = NULL;
634 struct stream_out *curr_out = NULL;
635 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
636 int i, num_devices, ret = 0;
637 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530638
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530639 list_for_each(node, &adev->usecase_list) {
640 uc = node_to_item(node, struct audio_usecase, list);
641 curr_out = (struct stream_out*) uc->stream.out;
642 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
643 /*
644 *Split snd device for existing combo use case
645 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
646 */
647 ret = platform_split_snd_device(adev->platform,
648 uc->out_snd_device,
649 &num_devices,
650 split_snd_devices);
651 if (ret < 0 || num_devices == 0) {
652 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
653 split_snd_devices[0] = uc->out_snd_device;
654 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800655 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530656 for (i = 0; i < num_devices; i++) {
657 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
658 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
659 if((new_backend_idx == HEADPHONE_BACKEND) &&
660 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
661 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
662 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
663 __func__);
664 enable_asrc_mode(adev);
665 break;
666 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
667 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
668 (usecase_backend_idx == HEADPHONE_BACKEND)) {
669 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
670 __func__);
671 disable_audio_route(adev, uc);
672 disable_snd_device(adev, uc->out_snd_device);
673 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
674 if (new_backend_idx == DSD_NATIVE_BACKEND)
675 audio_route_apply_and_update_path(adev->audio_route,
676 "hph-true-highquality-mode");
677 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
678 (curr_out->bit_width >= 24))
679 audio_route_apply_and_update_path(adev->audio_route,
680 "hph-highquality-mode");
681 enable_asrc_mode(adev);
682 enable_snd_device(adev, uc->out_snd_device);
683 enable_audio_route(adev, uc);
684 break;
685 }
686 }
687 // reset split devices count
688 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800689 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530690 if (adev->asrc_mode_enabled)
691 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530692 }
693 }
694 }
695}
696
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700697int pcm_ioctl(struct pcm *pcm, int request, ...)
698{
699 va_list ap;
700 void * arg;
701 int pcm_fd = *(int*)pcm;
702
703 va_start(ap, request);
704 arg = va_arg(ap, void *);
705 va_end(ap);
706
707 return ioctl(pcm_fd, request, arg);
708}
709
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700710int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700711 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800712{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700714 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530715 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800716
717 if (usecase == NULL)
718 return -EINVAL;
719
720 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
721
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800722 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700723 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800724 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700725 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800726
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800727#ifdef DS1_DOLBY_DAP_ENABLED
728 audio_extn_dolby_set_dmid(adev);
729 audio_extn_dolby_set_endpoint(adev);
730#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700731 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700732 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530733 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700734 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530735 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530736 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
737 out = usecase->stream.out;
738 if (out && out->compr)
739 audio_extn_utils_compress_set_clk_rec_mode(usecase);
740 }
741
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800742 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700743 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700744 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700745 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746 ALOGV("%s: exit", __func__);
747 return 0;
748}
749
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700750int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700751 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700754 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800755
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530756 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800757 return -EINVAL;
758
759 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700760 if (usecase->type == PCM_CAPTURE)
761 snd_device = usecase->in_snd_device;
762 else
763 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800764 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700765 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700766 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700767 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700768 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530769 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800770 ALOGV("%s: exit", __func__);
771 return 0;
772}
773
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700774int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700775 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530777 int i, num_devices = 0;
778 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700779 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
780
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800781 if (snd_device < SND_DEVICE_MIN ||
782 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800783 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800784 return -EINVAL;
785 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700786
787 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700788
789 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
790 ALOGE("%s: Invalid sound device returned", __func__);
791 return -EINVAL;
792 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700793 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700794 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700795 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700796 return 0;
797 }
798
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530799
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700800 if (audio_extn_spkr_prot_is_enabled())
801 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700802
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800803 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
804 audio_extn_spkr_prot_is_enabled()) {
805 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700806 adev->snd_dev_ref_cnt[snd_device]--;
807 return -EINVAL;
808 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200809 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800810 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800811 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200812 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800813 return -EINVAL;
814 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700815 } else if (platform_split_snd_device(adev->platform,
816 snd_device,
817 &num_devices,
818 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530819 for (i = 0; i < num_devices; i++) {
820 enable_snd_device(adev, new_snd_devices[i]);
821 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800822 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700823 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530824
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530825
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530826 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
827 (audio_extn_a2dp_start_playback() < 0)) {
828 ALOGE(" fail to configure A2dp control path ");
829 return -EINVAL;
830 }
831
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700832 /* due to the possibility of calibration overwrite between listen
833 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700834 audio_extn_sound_trigger_update_device_status(snd_device,
835 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530836 audio_extn_listen_update_device_status(snd_device,
837 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700838 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700839 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700840 audio_extn_sound_trigger_update_device_status(snd_device,
841 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530842 audio_extn_listen_update_device_status(snd_device,
843 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700844 return -EINVAL;
845 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300846 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700847 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530848
849 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
850 !adev->native_playback_enabled &&
851 audio_is_true_native_stream_active(adev)) {
852 ALOGD("%s: %d: napb: enabling native mode in hardware",
853 __func__, __LINE__);
854 audio_route_apply_and_update_path(adev->audio_route,
855 "true-native-mode");
856 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530857 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800858 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800859 return 0;
860}
861
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700862int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700863 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800864{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530865 int i, num_devices = 0;
866 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700867 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
868
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800869 if (snd_device < SND_DEVICE_MIN ||
870 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800871 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800872 return -EINVAL;
873 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
875 ALOGE("%s: device ref cnt is already 0", __func__);
876 return -EINVAL;
877 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700880
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700881 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
882 ALOGE("%s: Invalid sound device returned", __func__);
883 return -EINVAL;
884 }
885
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700886 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700887 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530888
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800889 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
890 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700891 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700892 } else if (platform_split_snd_device(adev->platform,
893 snd_device,
894 &num_devices,
895 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530896 for (i = 0; i < num_devices; i++) {
897 disable_snd_device(adev, new_snd_devices[i]);
898 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300899 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700900 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300901 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700902
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530903 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
904 audio_extn_a2dp_stop_playback();
905
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700906 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530907 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530908 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
909 adev->native_playback_enabled) {
910 ALOGD("%s: %d: napb: disabling native mode in hardware",
911 __func__, __LINE__);
912 audio_route_reset_and_update_path(adev->audio_route,
913 "true-native-mode");
914 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530915 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
916 adev->asrc_mode_enabled) {
917 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530918 disable_asrc_mode(adev);
919 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530920 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530921
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200922 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700923 audio_extn_sound_trigger_update_device_status(snd_device,
924 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530925 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800926 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800929 return 0;
930}
931
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700932/*
933 legend:
934 uc - existing usecase
935 new_uc - new usecase
936 d1, d11, d2 - SND_DEVICE enums
937 a1, a2 - corresponding ANDROID device enums
938 B1, B2 - backend strings
939
940case 1
941 uc->dev d1 (a1) B1
942 new_uc->dev d1 (a1), d2 (a2) B1, B2
943
944 resolution: disable and enable uc->dev on d1
945
946case 2
947 uc->dev d1 (a1) B1
948 new_uc->dev d11 (a1) B1
949
950 resolution: need to switch uc since d1 and d11 are related
951 (e.g. speaker and voice-speaker)
952 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
953
954case 3
955 uc->dev d1 (a1) B1
956 new_uc->dev d2 (a2) B2
957
958 resolution: no need to switch uc
959
960case 4
961 uc->dev d1 (a1) B1
962 new_uc->dev d2 (a2) B1
963
964 resolution: disable enable uc-dev on d2 since backends match
965 we cannot enable two streams on two different devices if they
966 share the same backend. e.g. if offload is on speaker device using
967 QUAD_MI2S backend and a low-latency stream is started on voice-handset
968 using the same backend, offload must also be switched to voice-handset.
969
970case 5
971 uc->dev d1 (a1) B1
972 new_uc->dev d1 (a1), d2 (a2) B1
973
974 resolution: disable enable uc-dev on d2 since backends match
975 we cannot enable two streams on two different devices if they
976 share the same backend.
977
978case 6
979 uc->dev d1 (a1) B1
980 new_uc->dev d2 (a1) B2
981
982 resolution: no need to switch
983
984case 7
985 uc->dev d1 (a1), d2 (a2) B1, B2
986 new_uc->dev d1 (a1) B1
987
988 resolution: no need to switch
989
990*/
991static snd_device_t derive_playback_snd_device(void * platform,
992 struct audio_usecase *uc,
993 struct audio_usecase *new_uc,
994 snd_device_t new_snd_device)
995{
996 audio_devices_t a1 = uc->stream.out->devices;
997 audio_devices_t a2 = new_uc->stream.out->devices;
998
999 snd_device_t d1 = uc->out_snd_device;
1000 snd_device_t d2 = new_snd_device;
1001
1002 // Treat as a special case when a1 and a2 are not disjoint
1003 if ((a1 != a2) && (a1 & a2)) {
1004 snd_device_t d3[2];
1005 int num_devices = 0;
1006 int ret = platform_split_snd_device(platform,
1007 popcount(a1) > 1 ? d1 : d2,
1008 &num_devices,
1009 d3);
1010 if (ret < 0) {
1011 if (ret != -ENOSYS) {
1012 ALOGW("%s failed to split snd_device %d",
1013 __func__,
1014 popcount(a1) > 1 ? d1 : d2);
1015 }
1016 goto end;
1017 }
1018
1019 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1020 // But if it does happen, we need to give priority to d2 if
1021 // the combo devices active on the existing usecase share a backend.
1022 // This is because we cannot have a usecase active on a combo device
1023 // and a new usecase requests one device in this combo pair.
1024 if (platform_check_backends_match(d3[0], d3[1])) {
1025 return d2; // case 5
1026 } else {
1027 return d1; // case 1
1028 }
1029 } else {
1030 if (platform_check_backends_match(d1, d2)) {
1031 return d2; // case 2, 4
1032 } else {
1033 return d1; // case 6, 3
1034 }
1035 }
1036
1037end:
1038 return d2; // return whatever was calculated before.
1039}
1040
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301042 struct audio_usecase *uc_info,
1043 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044{
1045 struct listnode *node;
1046 struct audio_usecase *usecase;
1047 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301048 snd_device_t uc_derive_snd_device;
1049 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001051 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301052 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001053 /*
1054 * This function is to make sure that all the usecases that are active on
1055 * the hardware codec backend are always routed to any one device that is
1056 * handled by the hardware codec.
1057 * For example, if low-latency and deep-buffer usecases are currently active
1058 * on speaker and out_set_parameters(headset) is received on low-latency
1059 * output, then we have to make sure deep-buffer is also switched to headset,
1060 * because of the limitation that both the devices cannot be enabled
1061 * at the same time as they share the same backend.
1062 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001063 /*
1064 * This call is to check if we need to force routing for a particular stream
1065 * If there is a backend configuration change for the device when a
1066 * new stream starts, then ADM needs to be closed and re-opened with the new
1067 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001068 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001069 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001070 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1071 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301072 /* For a2dp device reconfigure all active sessions
1073 * with new AFE encoder format based on a2dp state
1074 */
1075 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1076 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1077 audio_extn_a2dp_is_force_device_switch()) {
1078 force_routing = true;
1079 force_restart_session = true;
1080 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301081 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1082
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001084 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001085 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001086 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1087 switch_device[i] = false;
1088
1089 list_for_each(node, &adev->usecase_list) {
1090 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001091
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301092 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1093 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301094 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301095 platform_get_snd_device_name(usecase->out_snd_device),
1096 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301097 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1098 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1099 usecase, uc_info, snd_device);
1100 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1101 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1102 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1103 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1104 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1105 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1106 ((force_restart_session) ||
1107 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301108 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1109 __func__, use_case_table[usecase->id],
1110 platform_get_snd_device_name(usecase->out_snd_device));
1111 disable_audio_route(adev, usecase);
1112 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301113 /* Enable existing usecase on derived playback device */
1114 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301115 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301116 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 }
1118 }
1119
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301120 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1121 num_uc_to_switch);
1122
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001124 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301126 /* Make sure the previous devices to be disabled first and then enable the
1127 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 list_for_each(node, &adev->usecase_list) {
1129 usecase = node_to_item(node, struct audio_usecase, list);
1130 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001131 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001132 }
1133 }
1134
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001135 list_for_each(node, &adev->usecase_list) {
1136 usecase = node_to_item(node, struct audio_usecase, list);
1137 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301138 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001139 }
1140 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 /* Re-route all the usecases on the shared backend other than the
1143 specified usecase to new snd devices */
1144 list_for_each(node, &adev->usecase_list) {
1145 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301146 /* Update the out_snd_device only before enabling the audio route */
1147 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301148 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301149 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301150 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301151 use_case_table[usecase->id],
1152 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001153 /* Update voc calibration before enabling VoIP route */
1154 if (usecase->type == VOIP_CALL)
1155 status = platform_switch_voice_call_device_post(adev->platform,
1156 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001157 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301158 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301159 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001160 }
1161 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001162 }
1163}
1164
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301165static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001166 struct audio_usecase *uc_info,
1167 snd_device_t snd_device)
1168{
1169 struct listnode *node;
1170 struct audio_usecase *usecase;
1171 bool switch_device[AUDIO_USECASE_MAX];
1172 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301173 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001174 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001175
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301176 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1177 snd_device);
1178 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301179
1180 /*
1181 * Make sure out devices is checked against out codec backend device and
1182 * also in devices against in codec backend. Checking out device against in
1183 * codec backend or vice versa causes issues.
1184 */
1185 if (uc_info->type == PCM_CAPTURE)
1186 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001187 /*
1188 * This function is to make sure that all the active capture usecases
1189 * are always routed to the same input sound device.
1190 * For example, if audio-record and voice-call usecases are currently
1191 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1192 * is received for voice call then we have to make sure that audio-record
1193 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1194 * because of the limitation that two devices cannot be enabled
1195 * at the same time if they share the same backend.
1196 */
1197 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1198 switch_device[i] = false;
1199
1200 list_for_each(node, &adev->usecase_list) {
1201 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301202 /*
1203 * TODO: Enhance below condition to handle BT sco/USB multi recording
1204 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001205 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001206 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301207 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301208 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301209 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301210 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001211 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1213 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001214 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001215 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216 switch_device[usecase->id] = true;
1217 num_uc_to_switch++;
1218 }
1219 }
1220
1221 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001222 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001223
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301224 /* Make sure the previous devices to be disabled first and then enable the
1225 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001226 list_for_each(node, &adev->usecase_list) {
1227 usecase = node_to_item(node, struct audio_usecase, list);
1228 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001229 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001230 }
1231 }
1232
1233 list_for_each(node, &adev->usecase_list) {
1234 usecase = node_to_item(node, struct audio_usecase, list);
1235 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001236 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001237 }
1238 }
1239
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001240 /* Re-route all the usecases on the shared backend other than the
1241 specified usecase to new snd devices */
1242 list_for_each(node, &adev->usecase_list) {
1243 usecase = node_to_item(node, struct audio_usecase, list);
1244 /* Update the in_snd_device only before enabling the audio route */
1245 if (switch_device[usecase->id] ) {
1246 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001247 if (usecase->type != VOICE_CALL) {
1248 /* Update voc calibration before enabling VoIP route */
1249 if (usecase->type == VOIP_CALL)
1250 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001251 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001252 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301253 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001254 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001255 }
1256 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001257 }
1258}
1259
Mingming Yin3a941d42016-02-17 18:08:05 -08001260static void reset_hdmi_sink_caps(struct stream_out *out) {
1261 int i = 0;
1262
1263 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1264 out->supported_channel_masks[i] = 0;
1265 }
1266 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1267 out->supported_formats[i] = 0;
1268 }
1269 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1270 out->supported_sample_rates[i] = 0;
1271 }
1272}
1273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001274/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001275static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276{
Mingming Yin3a941d42016-02-17 18:08:05 -08001277 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001278 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001279
Mingming Yin3a941d42016-02-17 18:08:05 -08001280 reset_hdmi_sink_caps(out);
1281
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001282 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001283 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001284 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001285 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001286 }
1287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001290 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001291 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001292 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1293 case 6:
1294 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1295 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1296 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1297 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1298 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1299 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300 break;
1301 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001302 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001303 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001304 break;
1305 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001306
1307 // check channel format caps
1308 i = 0;
1309 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1310 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1311 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1312 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1313 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1314 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1315 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1316 }
1317
Ben Romberger1aaaf862017-04-06 17:49:46 -07001318 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1319 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1320 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1321 }
1322
Mingming Yin3a941d42016-02-17 18:08:05 -08001323 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1324 ALOGV(":%s HDMI supports DTS format", __func__);
1325 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1326 }
1327
1328 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1329 ALOGV(":%s HDMI supports DTS HD format", __func__);
1330 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1331 }
1332
1333
1334 // check sample rate caps
1335 i = 0;
1336 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1337 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1338 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1339 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1340 }
1341 }
1342
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001343 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344}
1345
Alexy Josephb1379942016-01-29 15:49:38 -08001346audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001347 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001348{
1349 struct audio_usecase *usecase;
1350 struct listnode *node;
1351
1352 list_for_each(node, &adev->usecase_list) {
1353 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001354 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001355 ALOGV("%s: usecase id %d", __func__, usecase->id);
1356 return usecase->id;
1357 }
1358 }
1359 return USECASE_INVALID;
1360}
1361
Alexy Josephb1379942016-01-29 15:49:38 -08001362struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001363 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001364{
1365 struct audio_usecase *usecase;
1366 struct listnode *node;
1367
1368 list_for_each(node, &adev->usecase_list) {
1369 usecase = node_to_item(node, struct audio_usecase, list);
1370 if (usecase->id == uc_id)
1371 return usecase;
1372 }
1373 return NULL;
1374}
1375
Dhananjay Kumard4833242016-10-06 22:09:12 +05301376struct stream_in *get_next_active_input(const struct audio_device *adev)
1377{
1378 struct audio_usecase *usecase;
1379 struct listnode *node;
1380
1381 list_for_each_reverse(node, &adev->usecase_list) {
1382 usecase = node_to_item(node, struct audio_usecase, list);
1383 if (usecase->type == PCM_CAPTURE)
1384 return usecase->stream.in;
1385 }
1386 return NULL;
1387}
1388
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301389/*
1390 * is a true native playback active
1391 */
1392bool audio_is_true_native_stream_active(struct audio_device *adev)
1393{
1394 bool active = false;
1395 int i = 0;
1396 struct listnode *node;
1397
1398 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1399 ALOGV("%s:napb: not in true mode or non hdphones device",
1400 __func__);
1401 active = false;
1402 goto exit;
1403 }
1404
1405 list_for_each(node, &adev->usecase_list) {
1406 struct audio_usecase *uc;
1407 uc = node_to_item(node, struct audio_usecase, list);
1408 struct stream_out *curr_out =
1409 (struct stream_out*) uc->stream.out;
1410
1411 if (curr_out && PCM_PLAYBACK == uc->type) {
1412 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1413 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1414 uc->id, curr_out->sample_rate,
1415 curr_out->bit_width,
1416 platform_get_snd_device_name(uc->out_snd_device));
1417
1418 if (is_offload_usecase(uc->id) &&
1419 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1420 active = true;
1421 ALOGD("%s:napb:native stream detected", __func__);
1422 }
1423 }
1424 }
1425exit:
1426 return active;
1427}
1428
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301429/*
1430 * if native DSD playback active
1431 */
1432bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1433{
1434 bool active = false;
1435 struct listnode *node = NULL;
1436 struct audio_usecase *uc = NULL;
1437 struct stream_out *curr_out = NULL;
1438
1439 list_for_each(node, &adev->usecase_list) {
1440 uc = node_to_item(node, struct audio_usecase, list);
1441 curr_out = (struct stream_out*) uc->stream.out;
1442
1443 if (curr_out && PCM_PLAYBACK == uc->type &&
1444 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1445 active = true;
1446 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301447 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301448 }
1449 }
1450 return active;
1451}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301452
1453static bool force_device_switch(struct audio_usecase *usecase)
1454{
1455 bool ret = false;
1456 bool is_it_true_mode = false;
1457
1458 if (is_offload_usecase(usecase->id) &&
1459 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001460 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1461 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1462 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301463 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1464 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1465 (!is_it_true_mode && adev->native_playback_enabled)){
1466 ret = true;
1467 ALOGD("napb: time to toggle native mode");
1468 }
1469 }
1470
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301471 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301472 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1473 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301474 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001475 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301476 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301477 ALOGD("Force a2dp device switch to update new encoder config");
1478 ret = true;
1479 }
1480
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301481 return ret;
1482}
1483
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001484int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001486 snd_device_t out_snd_device = SND_DEVICE_NONE;
1487 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001488 struct audio_usecase *usecase = NULL;
1489 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001490 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001491 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001492 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001493 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301495 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1496
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497 usecase = get_usecase_from_list(adev, uc_id);
1498 if (usecase == NULL) {
1499 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1500 return -EINVAL;
1501 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001503 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001504 (usecase->type == VOIP_CALL) ||
1505 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301506 if(usecase->stream.out == NULL) {
1507 ALOGE("%s: stream.out is NULL", __func__);
1508 return -EINVAL;
1509 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001510 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001511 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001512 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001513 usecase->devices = usecase->stream.out->devices;
1514 } else {
1515 /*
1516 * If the voice call is active, use the sound devices of voice call usecase
1517 * so that it would not result any device switch. All the usecases will
1518 * be switched to new device when select_devices() is called for voice call
1519 * usecase. This is to avoid switching devices for voice call when
1520 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001521 * choose voice call device only if the use case device is
1522 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001523 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001524 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001525 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001526 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001527 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1528 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301529 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1530 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001531 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 in_snd_device = vc_usecase->in_snd_device;
1533 out_snd_device = vc_usecase->out_snd_device;
1534 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001535 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001536 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001537 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh02ef86f2017-04-21 15:36:04 +08001538 if (usecase->stream.out != NULL) {
1539 out_snd_device_backend_match = platform_check_backends_match(
1540 voip_usecase->out_snd_device,
1541 platform_get_output_snd_device(
1542 adev->platform,
1543 usecase->stream.out));
1544 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001545 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001546 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1547 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001548 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001549 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001550 in_snd_device = voip_usecase->in_snd_device;
1551 out_snd_device = voip_usecase->out_snd_device;
1552 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001553 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001554 hfp_ucid = audio_extn_hfp_get_usecase();
1555 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001556 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001557 in_snd_device = hfp_usecase->in_snd_device;
1558 out_snd_device = hfp_usecase->out_snd_device;
1559 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560 }
1561 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301562 if (usecase->stream.out == NULL) {
1563 ALOGE("%s: stream.out is NULL", __func__);
1564 return -EINVAL;
1565 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 usecase->devices = usecase->stream.out->devices;
1567 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001568 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001569 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001570 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001571 if (usecase->stream.out == adev->primary_output &&
1572 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001573 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001574 select_devices(adev, adev->active_input->usecase);
1575 }
1576 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301578 if (usecase->stream.in == NULL) {
1579 ALOGE("%s: stream.in is NULL", __func__);
1580 return -EINVAL;
1581 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001582 usecase->devices = usecase->stream.in->device;
1583 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001584 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001585 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001586 if (adev->active_input &&
1587 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301588 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1589 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1590 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001591 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001592 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001593 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1594 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001595 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001596 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001597 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001598 }
1599 }
1600
1601 if (out_snd_device == usecase->out_snd_device &&
1602 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301603
1604 if (!force_device_switch(usecase))
1605 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 }
1607
sangwoobc677242013-08-08 16:53:43 +09001608 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001609 out_snd_device, platform_get_snd_device_name(out_snd_device),
1610 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 /*
1613 * Limitation: While in call, to do a device switch we need to disable
1614 * and enable both RX and TX devices though one of them is same as current
1615 * device.
1616 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001617 if ((usecase->type == VOICE_CALL) &&
1618 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1619 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001620 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001621 }
1622
1623 if (((usecase->type == VOICE_CALL) ||
1624 (usecase->type == VOIP_CALL)) &&
1625 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1626 /* Disable sidetone only if voice/voip call already exists */
1627 if (voice_is_call_state_active(adev) ||
1628 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001629 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001630
1631 /* Disable aanc only if voice call exists */
1632 if (voice_is_call_state_active(adev))
1633 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001634 }
1635
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001636 /* Disable current sound devices */
1637 if (usecase->out_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->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001640 }
1641
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001643 disable_audio_route(adev, usecase);
1644 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 }
1646
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001647 /* Applicable only on the targets that has external modem.
1648 * New device information should be sent to modem before enabling
1649 * the devices to reduce in-call device switch time.
1650 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001651 if ((usecase->type == VOICE_CALL) &&
1652 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1653 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001654 status = platform_switch_voice_call_enable_device_config(adev->platform,
1655 out_snd_device,
1656 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001657 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001658
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659 /* Enable new sound devices */
1660 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001661 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301662 if (platform_check_codec_asrc_support(adev->platform))
1663 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001664 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665 }
1666
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001667 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301668 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001669 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001670 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001671
Avinash Vaish71a8b972014-07-24 15:36:33 +05301672 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001673 status = platform_switch_voice_call_device_post(adev->platform,
1674 out_snd_device,
1675 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301676 enable_audio_route_for_voice_usecases(adev, usecase);
1677 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001678
sangwoo170731f2013-06-08 15:36:36 +09001679 usecase->in_snd_device = in_snd_device;
1680 usecase->out_snd_device = out_snd_device;
1681
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301682 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1683 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301684 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001685 if ((24 == usecase->stream.out->bit_width) &&
1686 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1687 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1688 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1689 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1690 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1691 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1692 /*
1693 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1694 * configured device sample rate, if not update the COPP rate to be equal to the
1695 * device sample rate, else open COPP at stream sample rate
1696 */
1697 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1698 usecase->stream.out->sample_rate,
1699 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301700 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1701 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001702 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1703 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1704 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1705 }
1706
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001707 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001708 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001709 audio_extn_gef_notify_device_config(
1710 usecase->stream.out->devices,
1711 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001712 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001713 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001714 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301715 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001716 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001717
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001718 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001719 /* Enable aanc only if voice call exists */
1720 if (voice_is_call_state_active(adev))
1721 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1722
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001723 /* Enable sidetone only if other voice/voip call already exists */
1724 if (voice_is_call_state_active(adev) ||
1725 voice_extn_compress_voip_is_started(adev))
1726 voice_set_sidetone(adev, out_snd_device, true);
1727 }
1728
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001729 /* Applicable only on the targets that has external modem.
1730 * Enable device command should be sent to modem only after
1731 * enabling voice call mixer controls
1732 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001733 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001734 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1735 out_snd_device,
1736 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301737 ALOGD("%s: done",__func__);
1738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739 return status;
1740}
1741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742static int stop_input_stream(struct stream_in *in)
1743{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301744 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 struct audio_usecase *uc_info;
1746 struct audio_device *adev = in->dev;
1747
Eric Laurent994a6932013-07-17 11:51:42 -07001748 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 uc_info = get_usecase_from_list(adev, in->usecase);
1751 if (uc_info == NULL) {
1752 ALOGE("%s: Could not find the usecase (%d) in the list",
1753 __func__, in->usecase);
1754 return -EINVAL;
1755 }
1756
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001757 /* Close in-call recording streams */
1758 voice_check_and_stop_incall_rec_usecase(adev, in);
1759
Eric Laurent150dbfe2013-02-27 14:31:02 -08001760 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001761 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001762
1763 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001764 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001766 list_remove(&uc_info->list);
1767 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001769 adev->active_input = get_next_active_input(adev);
1770
Eric Laurent994a6932013-07-17 11:51:42 -07001771 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772 return ret;
1773}
1774
1775int start_input_stream(struct stream_in *in)
1776{
1777 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001778 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779 struct audio_usecase *uc_info;
1780 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301781 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782
Mingming Yin2664a5b2015-09-03 10:53:11 -07001783 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1784 if (get_usecase_from_list(adev, usecase) == NULL)
1785 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301786 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1787 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001788
Naresh Tanniru80659832014-06-04 18:17:56 +05301789
1790 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301791 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301792 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301793 goto error_config;
1794 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301795
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001796 /* Check if source matches incall recording usecase criteria */
1797 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1798 if (ret)
1799 goto error_config;
1800 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001801 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1802
1803 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1804 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1805 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001806 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001807 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001808
Eric Laurentb23d5282013-05-14 15:27:20 -07001809 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 if (in->pcm_device_id < 0) {
1811 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1812 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001813 ret = -EINVAL;
1814 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001816
1817 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001819
1820 if (!uc_info) {
1821 ret = -ENOMEM;
1822 goto error_config;
1823 }
1824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825 uc_info->id = in->usecase;
1826 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001827 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001828 uc_info->devices = in->device;
1829 uc_info->in_snd_device = SND_DEVICE_NONE;
1830 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001832 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301833 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1834 adev->perf_lock_opts,
1835 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301838 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1839 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001840
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301841 if (audio_extn_cin_attached_usecase(in->usecase)) {
1842 ret = audio_extn_cin_start_input_stream(in);
1843 if (ret)
1844 goto error_open;
1845 else
1846 goto done_open;
1847 }
1848
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001849 unsigned int flags = PCM_IN;
1850 unsigned int pcm_open_retry_count = 0;
1851
1852 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1853 flags |= PCM_MMAP | PCM_NOIRQ;
1854 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001855 } else if (in->realtime) {
1856 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001857 }
1858
1859 while (1) {
1860 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1861 flags, &in->config);
1862 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1863 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1864 if (in->pcm != NULL) {
1865 pcm_close(in->pcm);
1866 in->pcm = NULL;
1867 }
1868 if (pcm_open_retry_count-- == 0) {
1869 ret = -EIO;
1870 goto error_open;
1871 }
1872 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1873 continue;
1874 }
1875 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001877
1878 ALOGV("%s: pcm_prepare", __func__);
1879 ret = pcm_prepare(in->pcm);
1880 if (ret < 0) {
1881 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1882 pcm_close(in->pcm);
1883 in->pcm = NULL;
1884 goto error_open;
1885 }
1886
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001887 register_in_stream(in);
1888 if (in->realtime) {
1889 ret = pcm_start(in->pcm);
1890 if (ret < 0)
1891 goto error_open;
1892 }
1893
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301894done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301895 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001896 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001897
Eric Laurentc8400632013-02-14 19:04:54 -08001898 return ret;
1899
1900error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301901 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001902 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001903error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301904 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301905 /*
1906 * sleep 50ms to allow sufficient time for kernel
1907 * drivers to recover incases like SSR.
1908 */
1909 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001910 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001911
1912 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913}
1914
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001915void lock_input_stream(struct stream_in *in)
1916{
1917 pthread_mutex_lock(&in->pre_lock);
1918 pthread_mutex_lock(&in->lock);
1919 pthread_mutex_unlock(&in->pre_lock);
1920}
1921
1922void lock_output_stream(struct stream_out *out)
1923{
1924 pthread_mutex_lock(&out->pre_lock);
1925 pthread_mutex_lock(&out->lock);
1926 pthread_mutex_unlock(&out->pre_lock);
1927}
1928
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001929/* must be called with out->lock locked */
1930static int send_offload_cmd_l(struct stream_out* out, int command)
1931{
1932 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1933
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001934 if (!cmd) {
1935 ALOGE("failed to allocate mem for command 0x%x", command);
1936 return -ENOMEM;
1937 }
1938
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 ALOGVV("%s %d", __func__, command);
1940
1941 cmd->cmd = command;
1942 list_add_tail(&out->offload_cmd_list, &cmd->node);
1943 pthread_cond_signal(&out->offload_cond);
1944 return 0;
1945}
1946
1947/* must be called iwth out->lock locked */
1948static void stop_compressed_output_l(struct stream_out *out)
1949{
1950 out->offload_state = OFFLOAD_STATE_IDLE;
1951 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001952 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001953 if (out->compr != NULL) {
1954 compress_stop(out->compr);
1955 while (out->offload_thread_blocked) {
1956 pthread_cond_wait(&out->cond, &out->lock);
1957 }
1958 }
1959}
1960
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001961bool is_offload_usecase(audio_usecase_t uc_id)
1962{
1963 unsigned int i;
1964 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1965 if (uc_id == offload_usecases[i])
1966 return true;
1967 }
1968 return false;
1969}
1970
Dhananjay Kumarac341582017-02-23 23:42:25 +05301971static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001972{
vivek mehta446c3962015-09-14 10:57:35 -07001973 audio_usecase_t ret_uc = USECASE_INVALID;
1974 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001975 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001976 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301977 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001978 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1979 else
1980 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001981
vivek mehta446c3962015-09-14 10:57:35 -07001982 pthread_mutex_lock(&adev->lock);
1983 if (get_usecase_from_list(adev, ret_uc) != NULL)
1984 ret_uc = USECASE_INVALID;
1985 pthread_mutex_unlock(&adev->lock);
1986
1987 return ret_uc;
1988 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001989
1990 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001991 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1992 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1993 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1994 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001995 break;
1996 }
1997 }
vivek mehta446c3962015-09-14 10:57:35 -07001998
1999 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2000 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002001}
2002
2003static void free_offload_usecase(struct audio_device *adev,
2004 audio_usecase_t uc_id)
2005{
vivek mehta446c3962015-09-14 10:57:35 -07002006 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002007 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002008
2009 if (!adev->multi_offload_enable)
2010 return;
2011
2012 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2013 if (offload_usecases[offload_uc_index] == uc_id) {
2014 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002015 break;
2016 }
2017 }
2018 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2019}
2020
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021static void *offload_thread_loop(void *context)
2022{
2023 struct stream_out *out = (struct stream_out *) context;
2024 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002025 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2028 set_sched_policy(0, SP_FOREGROUND);
2029 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2030
2031 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002032 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 for (;;) {
2034 struct offload_cmd *cmd = NULL;
2035 stream_callback_event_t event;
2036 bool send_callback = false;
2037
2038 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2039 __func__, list_empty(&out->offload_cmd_list),
2040 out->offload_state);
2041 if (list_empty(&out->offload_cmd_list)) {
2042 ALOGV("%s SLEEPING", __func__);
2043 pthread_cond_wait(&out->offload_cond, &out->lock);
2044 ALOGV("%s RUNNING", __func__);
2045 continue;
2046 }
2047
2048 item = list_head(&out->offload_cmd_list);
2049 cmd = node_to_item(item, struct offload_cmd, node);
2050 list_remove(item);
2051
2052 ALOGVV("%s STATE %d CMD %d out->compr %p",
2053 __func__, out->offload_state, cmd->cmd, out->compr);
2054
2055 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2056 free(cmd);
2057 break;
2058 }
2059
2060 if (out->compr == NULL) {
2061 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002062 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 pthread_cond_signal(&out->cond);
2064 continue;
2065 }
2066 out->offload_thread_blocked = true;
2067 pthread_mutex_unlock(&out->lock);
2068 send_callback = false;
2069 switch(cmd->cmd) {
2070 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002071 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002072 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002073 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002074 send_callback = true;
2075 event = STREAM_CBK_EVENT_WRITE_READY;
2076 break;
2077 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002078 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302079 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002080 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302081 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002082 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302083 if (ret < 0)
2084 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302085 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302086 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002087 compress_drain(out->compr);
2088 else
2089 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302090 if (ret != -ENETRESET) {
2091 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302092 pthread_mutex_lock(&out->lock);
2093 out->send_new_metadata = 1;
2094 out->send_next_track_params = true;
2095 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302096 event = STREAM_CBK_EVENT_DRAIN_READY;
2097 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2098 } else
2099 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002100 break;
2101 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002102 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002104 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002105 send_callback = true;
2106 event = STREAM_CBK_EVENT_DRAIN_READY;
2107 break;
2108 default:
2109 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2110 break;
2111 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002112 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113 out->offload_thread_blocked = false;
2114 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002115 if (send_callback && out->client_callback) {
2116 ALOGVV("%s: sending client_callback event %d", __func__, event);
2117 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002118 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 free(cmd);
2120 }
2121
2122 pthread_cond_signal(&out->cond);
2123 while (!list_empty(&out->offload_cmd_list)) {
2124 item = list_head(&out->offload_cmd_list);
2125 list_remove(item);
2126 free(node_to_item(item, struct offload_cmd, node));
2127 }
2128 pthread_mutex_unlock(&out->lock);
2129
2130 return NULL;
2131}
2132
2133static int create_offload_callback_thread(struct stream_out *out)
2134{
2135 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2136 list_init(&out->offload_cmd_list);
2137 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2138 offload_thread_loop, out);
2139 return 0;
2140}
2141
2142static int destroy_offload_callback_thread(struct stream_out *out)
2143{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002144 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145 stop_compressed_output_l(out);
2146 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2147
2148 pthread_mutex_unlock(&out->lock);
2149 pthread_join(out->offload_thread, (void **) NULL);
2150 pthread_cond_destroy(&out->offload_cond);
2151
2152 return 0;
2153}
2154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155static int stop_output_stream(struct stream_out *out)
2156{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302157 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 struct audio_usecase *uc_info;
2159 struct audio_device *adev = out->dev;
2160
Eric Laurent994a6932013-07-17 11:51:42 -07002161 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002162 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 uc_info = get_usecase_from_list(adev, out->usecase);
2164 if (uc_info == NULL) {
2165 ALOGE("%s: Could not find the usecase (%d) in the list",
2166 __func__, out->usecase);
2167 return -EINVAL;
2168 }
2169
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002170 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302171 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002172 if (adev->visualizer_stop_output != NULL)
2173 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002174
2175 audio_extn_dts_remove_state_notifier_node(out->usecase);
2176
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002177 if (adev->offload_effects_stop_output != NULL)
2178 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2179 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002180
Eric Laurent150dbfe2013-02-27 14:31:02 -08002181 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002182 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183
2184 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002185 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002187 list_remove(&uc_info->list);
2188 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002190 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302191 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002192 ALOGV("Disable passthrough , reset mixer to pcm");
2193 /* NO_PASSTHROUGH */
2194 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002195 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002196 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2197 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002198
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302199 /* Must be called after removing the usecase from list */
2200 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302201 audio_extn_keep_alive_start();
2202
Manish Dewangan14956cc2017-02-14 18:54:42 +05302203 /*reset delay_param to 0*/
2204 out->delay_param.start_delay = 0;
2205
Eric Laurent994a6932013-07-17 11:51:42 -07002206 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 return ret;
2208}
2209
2210int start_output_stream(struct stream_out *out)
2211{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213 struct audio_usecase *uc_info;
2214 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302215 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002216 char mixer_ctl_name[128];
2217 struct mixer_ctl *ctl = NULL;
2218 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002220 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2221 ret = -EINVAL;
2222 goto error_config;
2223 }
2224
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302225 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2226 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2227 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302228
Naresh Tanniru80659832014-06-04 18:17:56 +05302229 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302230 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302231 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302232 goto error_config;
2233 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302234
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302235 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2236 if (!audio_extn_a2dp_is_ready()) {
2237 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2238 //combo usecase just by pass a2dp
2239 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2240 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2241 } else {
2242 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2243 ret = -EAGAIN;
2244 goto error_config;
2245 }
2246 }
2247 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002248 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 if (out->pcm_device_id < 0) {
2250 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2251 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002252 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002253 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 }
2255
2256 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002257
2258 if (!uc_info) {
2259 ret = -ENOMEM;
2260 goto error_config;
2261 }
2262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263 uc_info->id = out->usecase;
2264 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002265 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002266 uc_info->devices = out->devices;
2267 uc_info->in_snd_device = SND_DEVICE_NONE;
2268 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002269 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302271 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2272 adev->perf_lock_opts,
2273 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302274
2275 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2276 audio_extn_keep_alive_stop();
2277 if (audio_extn_passthru_is_enabled() &&
2278 audio_extn_passthru_is_passthrough_stream(out)) {
2279 audio_extn_passthru_on_start(out);
2280 audio_extn_passthru_update_stream_configuration(adev, out);
2281 }
2282 }
2283
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002284 select_devices(adev, out->usecase);
2285
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002286 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2287 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002288 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002289 unsigned int flags = PCM_OUT;
2290 unsigned int pcm_open_retry_count = 0;
2291 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2292 flags |= PCM_MMAP | PCM_NOIRQ;
2293 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002294 } else if (out->realtime) {
2295 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002296 } else
2297 flags |= PCM_MONOTONIC;
2298
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002299 if ((adev->vr_audio_mode_enabled) &&
2300 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2301 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2302 "PCM_Dev %d Topology", out->pcm_device_id);
2303 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2304 if (!ctl) {
2305 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2306 __func__, mixer_ctl_name);
2307 } else {
2308 //if success use ULLPP
2309 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2310 __func__, mixer_ctl_name, out->pcm_device_id);
2311 //There is a still a possibility that some sessions
2312 // that request for FAST|RAW when 3D audio is active
2313 //can go through ULLPP. Ideally we expects apps to
2314 //listen to audio focus and stop concurrent playback
2315 //Also, we will look for mode flag (voice_in_communication)
2316 //before enabling the realtime flag.
2317 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2318 }
2319 }
2320
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002321 while (1) {
2322 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2323 flags, &out->config);
2324 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2325 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2326 if (out->pcm != NULL) {
2327 pcm_close(out->pcm);
2328 out->pcm = NULL;
2329 }
2330 if (pcm_open_retry_count-- == 0) {
2331 ret = -EIO;
2332 goto error_open;
2333 }
2334 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2335 continue;
2336 }
2337 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002339
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002340 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2341 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002342
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002343 ALOGV("%s: pcm_prepare", __func__);
2344 if (pcm_is_ready(out->pcm)) {
2345 ret = pcm_prepare(out->pcm);
2346 if (ret < 0) {
2347 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2348 pcm_close(out->pcm);
2349 out->pcm = NULL;
2350 goto error_open;
2351 }
2352 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302353 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2354 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002356 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2357 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002359 out->compr = compress_open(adev->snd_card,
2360 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 COMPRESS_IN, &out->compr_config);
2362 if (out->compr && !is_compress_ready(out->compr)) {
2363 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2364 compress_close(out->compr);
2365 out->compr = NULL;
2366 ret = -EIO;
2367 goto error_open;
2368 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302369 /* compress_open sends params of the track, so reset the flag here */
2370 out->is_compr_metadata_avail = false;
2371
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002372 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002374
Fred Oh3f43e742015-03-04 18:42:34 -08002375 /* Since small bufs uses blocking writes, a write will be blocked
2376 for the default max poll time (20s) in the event of an SSR.
2377 Reduce the poll time to observe and deal with SSR faster.
2378 */
Ashish Jain5106d362016-05-11 19:23:33 +05302379 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002380 compress_set_max_poll_wait(out->compr, 1000);
2381 }
2382
Manish Dewangan69426c82017-01-30 17:35:36 +05302383 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302384 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan27346042017-03-01 12:56:12 +05302385 /* set render window if it was set before compress_open() */
2386 if (out->render_window.render_ws != 0 && out->render_window.render_we != 0)
2387 audio_extn_utils_compress_set_render_window(out,
2388 &out->render_window);
Manish Dewangan14956cc2017-02-14 18:54:42 +05302389 audio_extn_utils_compress_set_start_delay(out, &out->delay_param);
Manish Dewangan69426c82017-01-30 17:35:36 +05302390
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002391 audio_extn_dts_create_state_notifier_node(out->usecase);
2392 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2393 popcount(out->channel_mask),
2394 out->playback_started);
2395
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002396#ifdef DS1_DOLBY_DDP_ENABLED
2397 if (audio_extn_is_dolby_format(out->format))
2398 audio_extn_dolby_send_ddp_endp_params(adev);
2399#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302400 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2401 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002402 if (adev->visualizer_start_output != NULL)
2403 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2404 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302405 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002406 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002409
2410 if (ret == 0) {
2411 register_out_stream(out);
2412 if (out->realtime) {
2413 ret = pcm_start(out->pcm);
2414 if (ret < 0)
2415 goto error_open;
2416 }
2417 }
2418
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302419 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002420 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002421
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002422 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302424 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002426error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302427 /*
2428 * sleep 50ms to allow sufficient time for kernel
2429 * drivers to recover incases like SSR.
2430 */
2431 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002432 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433}
2434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435static int check_input_parameters(uint32_t sample_rate,
2436 audio_format_t format,
2437 int channel_count)
2438{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002439 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302441 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2442 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2443 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002444 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302445 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002446
2447 switch (channel_count) {
2448 case 1:
2449 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302450 case 3:
2451 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002452 case 6:
2453 break;
2454 default:
2455 ret = -EINVAL;
2456 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457
2458 switch (sample_rate) {
2459 case 8000:
2460 case 11025:
2461 case 12000:
2462 case 16000:
2463 case 22050:
2464 case 24000:
2465 case 32000:
2466 case 44100:
2467 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302468 case 96000:
2469 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 break;
2471 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002472 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473 }
2474
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002475 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476}
2477
2478static size_t get_input_buffer_size(uint32_t sample_rate,
2479 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002480 int channel_count,
2481 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482{
2483 size_t size = 0;
2484
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002485 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2486 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002488 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002489 if (is_low_latency)
2490 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302491
2492 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002494 /* make sure the size is multiple of 32 bytes
2495 * At 48 kHz mono 16-bit PCM:
2496 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2497 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2498 */
2499 size += 0x1f;
2500 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002501
2502 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503}
2504
Ashish Jain058165c2016-09-28 23:18:48 +05302505static size_t get_output_period_size(uint32_t sample_rate,
2506 audio_format_t format,
2507 int channel_count,
2508 int duration /*in millisecs*/)
2509{
2510 size_t size = 0;
2511 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2512
2513 if ((duration == 0) || (sample_rate == 0) ||
2514 (bytes_per_sample == 0) || (channel_count == 0)) {
2515 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2516 bytes_per_sample, channel_count);
2517 return -EINVAL;
2518 }
2519
2520 size = (sample_rate *
2521 duration *
2522 bytes_per_sample *
2523 channel_count) / 1000;
2524 /*
2525 * To have same PCM samples for all channels, the buffer size requires to
2526 * be multiple of (number of channels * bytes per sample)
2527 * For writes to succeed, the buffer must be written at address which is multiple of 32
2528 */
2529 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2530
2531 return (size/(channel_count * bytes_per_sample));
2532}
2533
Ashish Jain5106d362016-05-11 19:23:33 +05302534static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2535{
2536 uint64_t actual_frames_rendered = 0;
2537 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2538
2539 /* This adjustment accounts for buffering after app processor.
2540 * It is based on estimated DSP latency per use case, rather than exact.
2541 */
2542 int64_t platform_latency = platform_render_latency(out->usecase) *
2543 out->sample_rate / 1000000LL;
2544
2545 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2546 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2547 * hence only estimate.
2548 */
2549 int64_t signed_frames = out->written - kernel_buffer_size;
2550
2551 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2552
2553 if (signed_frames > 0)
2554 actual_frames_rendered = signed_frames;
2555
2556 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2557 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2558 (long long int)out->written, (int)kernel_buffer_size,
2559 audio_bytes_per_sample(out->compr_config.codec->format),
2560 popcount(out->channel_mask));
2561
2562 return actual_frames_rendered;
2563}
2564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2566{
2567 struct stream_out *out = (struct stream_out *)stream;
2568
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002569 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570}
2571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002572static int out_set_sample_rate(struct audio_stream *stream __unused,
2573 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574{
2575 return -ENOSYS;
2576}
2577
2578static size_t out_get_buffer_size(const struct audio_stream *stream)
2579{
2580 struct stream_out *out = (struct stream_out *)stream;
2581
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302582 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2583 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2584 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2585 else
2586 return out->compr_config.fragment_size;
2587 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002588 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302589 else if (is_offload_usecase(out->usecase) &&
2590 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302591 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002592
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002593 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002594 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595}
2596
2597static uint32_t out_get_channels(const struct audio_stream *stream)
2598{
2599 struct stream_out *out = (struct stream_out *)stream;
2600
2601 return out->channel_mask;
2602}
2603
2604static audio_format_t out_get_format(const struct audio_stream *stream)
2605{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002606 struct stream_out *out = (struct stream_out *)stream;
2607
2608 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609}
2610
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002611static int out_set_format(struct audio_stream *stream __unused,
2612 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613{
2614 return -ENOSYS;
2615}
2616
2617static int out_standby(struct audio_stream *stream)
2618{
2619 struct stream_out *out = (struct stream_out *)stream;
2620 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002621
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302622 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2623 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002625 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002627 if (adev->adm_deregister_stream)
2628 adev->adm_deregister_stream(adev->adm_data, out->handle);
2629
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002630 if (is_offload_usecase(out->usecase))
2631 stop_compressed_output_l(out);
2632
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002633 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002635 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2636 voice_extn_compress_voip_close_output_stream(stream);
2637 pthread_mutex_unlock(&adev->lock);
2638 pthread_mutex_unlock(&out->lock);
2639 ALOGD("VOIP output entered standby");
2640 return 0;
2641 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002642 if (out->pcm) {
2643 pcm_close(out->pcm);
2644 out->pcm = NULL;
2645 }
2646 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002647 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302648 out->send_next_track_params = false;
2649 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002650 out->gapless_mdata.encoder_delay = 0;
2651 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652 if (out->compr != NULL) {
2653 compress_close(out->compr);
2654 out->compr = NULL;
2655 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002658 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 }
2660 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302661 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 return 0;
2663}
2664
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002665static int out_dump(const struct audio_stream *stream __unused,
2666 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667{
2668 return 0;
2669}
2670
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002671static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2672{
2673 int ret = 0;
2674 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002675
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002676 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002677 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002678 return -EINVAL;
2679 }
2680
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302681 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002682
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002683 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2684 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302685 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002686 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002687 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2688 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302689 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002690 }
2691
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002692 ALOGV("%s new encoder delay %u and padding %u", __func__,
2693 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2694
2695 return 0;
2696}
2697
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002698static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2699{
2700 return out == adev->primary_output || out == adev->voice_tx_output;
2701}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2704{
2705 struct stream_out *out = (struct stream_out *)stream;
2706 struct audio_device *adev = out->dev;
2707 struct str_parms *parms;
2708 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002709 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710
sangwoobc677242013-08-08 16:53:43 +09002711 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002712 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302714 if (!parms)
2715 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002716 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2717 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002719 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002720 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002722 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002723 * When HDMI cable is unplugged the music playback is paused and
2724 * the policy manager sends routing=0. But the audioflinger continues
2725 * to write data until standby time (3sec). As the HDMI core is
2726 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002727 * Avoid this by routing audio to speaker until standby.
2728 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002729 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2730 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302731 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002732 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2733 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002734 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302735 /*
2736 * When A2DP is disconnected the
2737 * music playback is paused and the policy manager sends routing=0
2738 * But the audioflingercontinues to write data until standby time
2739 * (3sec). As BT is turned off, the write gets blocked.
2740 * Avoid this by routing audio to speaker until standby.
2741 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002742 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302743 (val == AUDIO_DEVICE_NONE)) {
2744 val = AUDIO_DEVICE_OUT_SPEAKER;
2745 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302746 /* To avoid a2dp to sco overlapping / BT device improper state
2747 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302748 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302749 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2750 if (!audio_extn_a2dp_is_ready()) {
2751 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2752 //combo usecase just by pass a2dp
2753 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2754 val = AUDIO_DEVICE_OUT_SPEAKER;
2755 } else {
2756 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2757 /* update device to a2dp and don't route as BT returned error
2758 * However it is still possible a2dp routing called because
2759 * of current active device disconnection (like wired headset)
2760 */
2761 out->devices = val;
2762 pthread_mutex_unlock(&out->lock);
2763 pthread_mutex_unlock(&adev->lock);
2764 goto error;
2765 }
2766 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302767 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002768 /*
2769 * select_devices() call below switches all the usecases on the same
2770 * backend to the new device. Refer to check_usecases_codec_backend() in
2771 * the select_devices(). But how do we undo this?
2772 *
2773 * For example, music playback is active on headset (deep-buffer usecase)
2774 * and if we go to ringtones and select a ringtone, low-latency usecase
2775 * will be started on headset+speaker. As we can't enable headset+speaker
2776 * and headset devices at the same time, select_devices() switches the music
2777 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2778 * So when the ringtone playback is completed, how do we undo the same?
2779 *
2780 * We are relying on the out_set_parameters() call on deep-buffer output,
2781 * once the ringtone playback is ended.
2782 * NOTE: We should not check if the current devices are same as new devices.
2783 * Because select_devices() must be called to switch back the music
2784 * playback to headset.
2785 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002786 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002787 audio_devices_t new_dev = val;
2788 bool same_dev = out->devices == new_dev;
2789 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002790
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002791 if (output_drives_call(adev, out)) {
2792 if(!voice_is_in_call(adev)) {
2793 if (adev->mode == AUDIO_MODE_IN_CALL) {
2794 adev->current_call_output = out;
2795 ret = voice_start_call(adev);
2796 }
2797 } else {
2798 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002799 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002800 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002801 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002802
2803 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002804 if (!same_dev) {
2805 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302806 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2807 adev->perf_lock_opts,
2808 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002809 if (adev->adm_on_routing_change)
2810 adev->adm_on_routing_change(adev->adm_data,
2811 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002812 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002813 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302814 if (!same_dev)
2815 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002816 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002817 }
2818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002820 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002822
2823 if (out == adev->primary_output) {
2824 pthread_mutex_lock(&adev->lock);
2825 audio_extn_set_parameters(adev, parms);
2826 pthread_mutex_unlock(&adev->lock);
2827 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002828 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002829 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002830 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002831
2832 audio_extn_dts_create_state_notifier_node(out->usecase);
2833 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2834 popcount(out->channel_mask),
2835 out->playback_started);
2836
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002837 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002838 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002839
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302840 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2841 if (err >= 0) {
2842 strlcpy(out->profile, value, sizeof(out->profile));
2843 ALOGV("updating stream profile with value '%s'", out->profile);
2844 lock_output_stream(out);
2845 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2846 &adev->streams_output_cfg_list,
2847 out->devices, out->flags, out->format,
2848 out->sample_rate, out->bit_width,
2849 out->channel_mask, out->profile,
2850 &out->app_type_cfg);
2851 pthread_mutex_unlock(&out->lock);
2852 }
2853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002854 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302855error:
Eric Laurent994a6932013-07-17 11:51:42 -07002856 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 return ret;
2858}
2859
2860static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2861{
2862 struct stream_out *out = (struct stream_out *)stream;
2863 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002864 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 char value[256];
2866 struct str_parms *reply = str_parms_create();
2867 size_t i, j;
2868 int ret;
2869 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002870
2871 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002872 if (reply) {
2873 str_parms_destroy(reply);
2874 }
2875 if (query) {
2876 str_parms_destroy(query);
2877 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002878 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2879 return NULL;
2880 }
2881
Eric Laurent994a6932013-07-17 11:51:42 -07002882 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2884 if (ret >= 0) {
2885 value[0] = '\0';
2886 i = 0;
2887 while (out->supported_channel_masks[i] != 0) {
2888 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2889 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2890 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002891 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002893 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894 first = false;
2895 break;
2896 }
2897 }
2898 i++;
2899 }
2900 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2901 str = str_parms_to_str(reply);
2902 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002903 voice_extn_out_get_parameters(out, query, reply);
2904 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002905 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002906 free(str);
2907 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002908 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002910
Alexy Joseph62142aa2015-11-16 15:10:34 -08002911
2912 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2913 if (ret >= 0) {
2914 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302915 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2916 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002917 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302918 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002919 } else {
2920 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302921 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002922 }
2923 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002924 if (str)
2925 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002926 str = str_parms_to_str(reply);
2927 }
2928
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002929 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2930 if (ret >= 0) {
2931 value[0] = '\0';
2932 i = 0;
2933 first = true;
2934 while (out->supported_formats[i] != 0) {
2935 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2936 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2937 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002938 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002939 }
2940 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2941 first = false;
2942 break;
2943 }
2944 }
2945 i++;
2946 }
2947 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002948 if (str)
2949 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002950 str = str_parms_to_str(reply);
2951 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002952
2953 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2954 if (ret >= 0) {
2955 value[0] = '\0';
2956 i = 0;
2957 first = true;
2958 while (out->supported_sample_rates[i] != 0) {
2959 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2960 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2961 if (!first) {
2962 strlcat(value, "|", sizeof(value));
2963 }
2964 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2965 first = false;
2966 break;
2967 }
2968 }
2969 i++;
2970 }
2971 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2972 if (str)
2973 free(str);
2974 str = str_parms_to_str(reply);
2975 }
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977 str_parms_destroy(query);
2978 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002979 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 return str;
2981}
2982
2983static uint32_t out_get_latency(const struct audio_stream_out *stream)
2984{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002985 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002987 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988
Alexy Josephaa54c872014-12-03 02:46:47 -08002989 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302990 lock_output_stream(out);
2991 latency = audio_extn_utils_compress_get_dsp_latency(out);
2992 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002993 } else if (out->realtime) {
2994 // since the buffer won't be filled up faster than realtime,
2995 // return a smaller number
2996 if (out->config.rate)
2997 period_ms = (out->af_period_multiplier * out->config.period_size *
2998 1000) / (out->config.rate);
2999 else
3000 period_ms = 0;
3001 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003002 } else {
3003 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003005 }
3006
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003007 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3008 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3009 latency += audio_extn_a2dp_get_encoder_latency();
3010
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303011 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003012 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013}
3014
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303015static float AmpToDb(float amplification)
3016{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303017 float db = DSD_VOLUME_MIN_DB;
3018 if (amplification > 0) {
3019 db = 20 * log10(amplification);
3020 if(db < DSD_VOLUME_MIN_DB)
3021 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303022 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303023 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303024}
3025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026static int out_set_volume(struct audio_stream_out *stream, float left,
3027 float right)
3028{
Eric Laurenta9024de2013-04-04 09:19:12 -07003029 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 int volume[2];
3031
Eric Laurenta9024de2013-04-04 09:19:12 -07003032 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3033 /* only take left channel into account: the API is for stereo anyway */
3034 out->muted = (left == 0.0f);
3035 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003036 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303037 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003038 /*
3039 * Set mute or umute on HDMI passthrough stream.
3040 * Only take left channel into account.
3041 * Mute is 0 and unmute 1
3042 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303043 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303044 } else if (out->format == AUDIO_FORMAT_DSD){
3045 char mixer_ctl_name[128] = "DSD Volume";
3046 struct audio_device *adev = out->dev;
3047 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3048
3049 if (!ctl) {
3050 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3051 __func__, mixer_ctl_name);
3052 return -EINVAL;
3053 }
3054 volume[0] = (int)(AmpToDb(left));
3055 volume[1] = (int)(AmpToDb(right));
3056 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3057 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003058 } else {
3059 char mixer_ctl_name[128];
3060 struct audio_device *adev = out->dev;
3061 struct mixer_ctl *ctl;
3062 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003063 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003065 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3066 "Compress Playback %d Volume", pcm_device_id);
3067 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3068 if (!ctl) {
3069 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3070 __func__, mixer_ctl_name);
3071 return -EINVAL;
3072 }
3073 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3074 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3075 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3076 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003078 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 return -ENOSYS;
3081}
3082
3083static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3084 size_t bytes)
3085{
3086 struct stream_out *out = (struct stream_out *)stream;
3087 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303088 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003089 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003091 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303092
Naresh Tanniru80659832014-06-04 18:17:56 +05303093 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003094
Dhananjay Kumarac341582017-02-23 23:42:25 +05303095 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303096 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303097 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3098 pthread_mutex_unlock(&out->lock);
3099 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303100 } else {
3101 /* increase written size during SSR to avoid mismatch
3102 * with the written frames count in AF
3103 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003104 // bytes per frame
3105 size_t bpf = audio_bytes_per_sample(out->format) *
3106 audio_channel_count_from_out_mask(out->channel_mask);
3107 if (bpf != 0)
3108 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303109 ALOGD(" %s: sound card is not active/SSR state", __func__);
3110 ret= -EIO;
3111 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303112 }
3113 }
3114
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303115 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303116 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3117 if (audio_bytes_per_sample(out->format) != 0)
3118 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3119 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303120 goto exit;
3121 }
3122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003124 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003125 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003126 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3127 ret = voice_extn_compress_voip_start_output_stream(out);
3128 else
3129 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003130 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003131 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003133 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 goto exit;
3135 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003136
3137 if (last_known_cal_step != -1) {
3138 ALOGD("%s: retry previous failed cal level set", __func__);
3139 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3140 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142
Ashish Jain81eb2a82015-05-13 10:52:34 +05303143 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003144 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303145 adev->is_channel_status_set = true;
3146 }
3147
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003148 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003149 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003150 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003151 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003152 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3153 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303154 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3155 ALOGD("copl(%p):send next track params in gapless", out);
3156 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3157 out->send_next_track_params = false;
3158 out->is_compr_metadata_avail = false;
3159 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003160 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303161 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303162 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003163
Ashish Jain83a6cc22016-06-28 14:34:17 +05303164 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303165 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303166 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303167 pthread_mutex_unlock(&out->lock);
3168 return -EINVAL;
3169 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303170 audio_format_t dst_format = out->hal_op_format;
3171 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303172
3173 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3174 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3175
Ashish Jain83a6cc22016-06-28 14:34:17 +05303176 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303177 dst_format,
3178 buffer,
3179 src_format,
3180 frames);
3181
Ashish Jain83a6cc22016-06-28 14:34:17 +05303182 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303183 bytes_to_write);
3184
3185 /*Convert written bytes in audio flinger format*/
3186 if (ret > 0)
3187 ret = ((ret * format_to_bitwidth_table[out->format]) /
3188 format_to_bitwidth_table[dst_format]);
3189 }
3190 } else
3191 ret = compress_write(out->compr, buffer, bytes);
3192
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303193 if (ret < 0)
3194 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303195 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303196 /*msg to cb thread only if non blocking write is enabled*/
3197 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303198 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303200 } else if (-ENETRESET == ret) {
3201 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3202 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3203 pthread_mutex_unlock(&out->lock);
3204 out_standby(&out->stream.common);
3205 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003206 }
Ashish Jain5106d362016-05-11 19:23:33 +05303207 if ( ret == (ssize_t)bytes && !out->non_blocking)
3208 out->written += bytes;
3209
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303210 /* Call compr start only when non-zero bytes of data is there to be rendered */
3211 if (!out->playback_started && ret > 0) {
3212 int status = compress_start(out->compr);
3213 if (status < 0) {
3214 ret = status;
3215 ALOGE("%s: compr start failed with err %d", __func__, errno);
3216 goto exit;
3217 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003218 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003219 out->playback_started = 1;
3220 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003221
3222 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3223 popcount(out->channel_mask),
3224 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003225 }
3226 pthread_mutex_unlock(&out->lock);
3227 return ret;
3228 } else {
3229 if (out->pcm) {
3230 if (out->muted)
3231 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003232
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303233 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003234
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003235 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003236
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003237 if (out->config.rate)
3238 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3239 out->config.rate;
3240
3241 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3242
3243 request_out_focus(out, ns);
3244
3245 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003246 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003247 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303248 out->convert_buffer != NULL) {
3249
3250 memcpy_by_audio_format(out->convert_buffer,
3251 out->hal_op_format,
3252 buffer,
3253 out->hal_ip_format,
3254 out->config.period_size * out->config.channels);
3255
3256 ret = pcm_write(out->pcm, out->convert_buffer,
3257 (out->config.period_size *
3258 out->config.channels *
3259 format_to_bitwidth_table[out->hal_op_format]));
3260 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003261 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303262 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003263
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003264 release_out_focus(out);
3265
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303266 if (ret < 0)
3267 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303268 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3269 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3270 else
3271 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003272 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273 }
3274
3275exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303276 /* ToDo: There may be a corner case when SSR happens back to back during
3277 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303278 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303279 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303280 }
3281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282 pthread_mutex_unlock(&out->lock);
3283
3284 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003285 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003286 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303287 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303288 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303289 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303290 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303291 out->standby = true;
3292 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303294 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3295 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3296 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 }
3298 return bytes;
3299}
3300
3301static int out_get_render_position(const struct audio_stream_out *stream,
3302 uint32_t *dsp_frames)
3303{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003304 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303305 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003306
3307 if (dsp_frames == NULL)
3308 return -EINVAL;
3309
3310 *dsp_frames = 0;
3311 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003312 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303313
3314 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3315 * this operation and adev_close_output_stream(where out gets reset).
3316 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303317 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303318 *dsp_frames = get_actual_pcm_frames_rendered(out);
3319 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3320 return 0;
3321 }
3322
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003323 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303324 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303325 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303327 if (ret < 0)
3328 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003329 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303330 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003331 }
3332 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303333 if (-ENETRESET == ret) {
3334 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3335 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3336 return -EINVAL;
3337 } else if(ret < 0) {
3338 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3339 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303340 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3341 /*
3342 * Handle corner case where compress session is closed during SSR
3343 * and timestamp is queried
3344 */
3345 ALOGE(" ERROR: sound card not active, return error");
3346 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303347 } else {
3348 return 0;
3349 }
Zhou Song32a556e2015-05-05 10:46:56 +08003350 } else if (audio_is_linear_pcm(out->format)) {
3351 *dsp_frames = out->written;
3352 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 } else
3354 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355}
3356
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003357static int out_add_audio_effect(const struct audio_stream *stream __unused,
3358 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359{
3360 return 0;
3361}
3362
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003363static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3364 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365{
3366 return 0;
3367}
3368
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003369static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3370 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371{
3372 return -EINVAL;
3373}
3374
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003375static int out_get_presentation_position(const struct audio_stream_out *stream,
3376 uint64_t *frames, struct timespec *timestamp)
3377{
3378 struct stream_out *out = (struct stream_out *)stream;
3379 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003380 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003381
Ashish Jain5106d362016-05-11 19:23:33 +05303382 /* below piece of code is not guarded against any lock because audioFliner serializes
3383 * this operation and adev_close_output_stream( where out gets reset).
3384 */
3385 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303386 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303387 *frames = get_actual_pcm_frames_rendered(out);
3388 /* this is the best we can do */
3389 clock_gettime(CLOCK_MONOTONIC, timestamp);
3390 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3391 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3392 return 0;
3393 }
3394
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003395 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003396
Ashish Jain5106d362016-05-11 19:23:33 +05303397 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3398 ret = compress_get_tstamp(out->compr, &dsp_frames,
3399 &out->sample_rate);
3400 ALOGVV("%s rendered frames %ld sample_rate %d",
3401 __func__, dsp_frames, out->sample_rate);
3402 *frames = dsp_frames;
3403 if (ret < 0)
3404 ret = -errno;
3405 if (-ENETRESET == ret) {
3406 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3407 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3408 ret = -EINVAL;
3409 } else
3410 ret = 0;
3411 /* this is the best we can do */
3412 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003413 } else {
3414 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003415 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003416 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3417 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003418 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003419 // This adjustment accounts for buffering after app processor.
3420 // It is based on estimated DSP latency per use case, rather than exact.
3421 signed_frames -=
3422 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3423
Eric Laurent949a0892013-09-20 09:20:13 -07003424 // It would be unusual for this value to be negative, but check just in case ...
3425 if (signed_frames >= 0) {
3426 *frames = signed_frames;
3427 ret = 0;
3428 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003429 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303430 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3431 *frames = out->written;
3432 clock_gettime(CLOCK_MONOTONIC, timestamp);
3433 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003434 }
3435 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003436 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003437 return ret;
3438}
3439
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003440static int out_set_callback(struct audio_stream_out *stream,
3441 stream_callback_t callback, void *cookie)
3442{
3443 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003444 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003445
3446 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003447 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003448 out->client_callback = callback;
3449 out->client_cookie = cookie;
3450 if (out->adsp_hdlr_stream_handle) {
3451 ret = audio_extn_adsp_hdlr_stream_set_callback(
3452 out->adsp_hdlr_stream_handle,
3453 callback,
3454 cookie);
3455 if (ret)
3456 ALOGW("%s:adsp hdlr callback registration failed %d",
3457 __func__, ret);
3458 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003459 pthread_mutex_unlock(&out->lock);
3460 return 0;
3461}
3462
3463static int out_pause(struct audio_stream_out* stream)
3464{
3465 struct stream_out *out = (struct stream_out *)stream;
3466 int status = -ENOSYS;
3467 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003468 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003469 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003470 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003471 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303472 struct audio_device *adev = out->dev;
3473 int snd_scard_state = get_snd_card_state(adev);
3474
3475 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3476 status = compress_pause(out->compr);
3477
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003478 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003479
Mingming Yin21854652016-04-13 11:54:02 -07003480 if (audio_extn_passthru_is_active()) {
3481 ALOGV("offload use case, pause passthru");
3482 audio_extn_passthru_on_pause(out);
3483 }
3484
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303485 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003486 audio_extn_dts_notify_playback_state(out->usecase, 0,
3487 out->sample_rate, popcount(out->channel_mask),
3488 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003489 }
3490 pthread_mutex_unlock(&out->lock);
3491 }
3492 return status;
3493}
3494
3495static int out_resume(struct audio_stream_out* stream)
3496{
3497 struct stream_out *out = (struct stream_out *)stream;
3498 int status = -ENOSYS;
3499 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003500 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003501 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003503 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003504 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303505 struct audio_device *adev = out->dev;
3506 int snd_scard_state = get_snd_card_state(adev);
3507
Mingming Yin21854652016-04-13 11:54:02 -07003508 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3509 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3510 pthread_mutex_lock(&out->dev->lock);
3511 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003512 pthread_mutex_unlock(&out->dev->lock);
3513 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303514 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003515 }
3516 if (!status) {
3517 out->offload_state = OFFLOAD_STATE_PLAYING;
3518 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303519 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003520 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3521 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 }
3523 pthread_mutex_unlock(&out->lock);
3524 }
3525 return status;
3526}
3527
3528static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3529{
3530 struct stream_out *out = (struct stream_out *)stream;
3531 int status = -ENOSYS;
3532 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003533 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003534 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003535 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3536 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3537 else
3538 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3539 pthread_mutex_unlock(&out->lock);
3540 }
3541 return status;
3542}
3543
3544static int out_flush(struct audio_stream_out* stream)
3545{
3546 struct stream_out *out = (struct stream_out *)stream;
3547 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003548 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003549 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003550 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003551 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3552 stop_compressed_output_l(out);
3553 out->written = 0;
3554 } else {
3555 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3556 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003558 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003559 return 0;
3560 }
3561 return -ENOSYS;
3562}
3563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564/** audio_stream_in implementation **/
3565static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3566{
3567 struct stream_in *in = (struct stream_in *)stream;
3568
3569 return in->config.rate;
3570}
3571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003572static int in_set_sample_rate(struct audio_stream *stream __unused,
3573 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574{
3575 return -ENOSYS;
3576}
3577
3578static size_t in_get_buffer_size(const struct audio_stream *stream)
3579{
3580 struct stream_in *in = (struct stream_in *)stream;
3581
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003582 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3583 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003584 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3585 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303586 else if(audio_extn_cin_attached_usecase(in->usecase))
3587 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003588
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003589 return in->config.period_size * in->af_period_multiplier *
3590 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591}
3592
3593static uint32_t in_get_channels(const struct audio_stream *stream)
3594{
3595 struct stream_in *in = (struct stream_in *)stream;
3596
3597 return in->channel_mask;
3598}
3599
3600static audio_format_t in_get_format(const struct audio_stream *stream)
3601{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003602 struct stream_in *in = (struct stream_in *)stream;
3603
3604 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605}
3606
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003607static int in_set_format(struct audio_stream *stream __unused,
3608 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609{
3610 return -ENOSYS;
3611}
3612
3613static int in_standby(struct audio_stream *stream)
3614{
3615 struct stream_in *in = (struct stream_in *)stream;
3616 struct audio_device *adev = in->dev;
3617 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303618 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3619 stream, in->usecase, use_case_table[in->usecase]);
3620
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003621 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003622 if (!in->standby && in->is_st_session) {
3623 ALOGD("%s: sound trigger pcm stop lab", __func__);
3624 audio_extn_sound_trigger_stop_lab(in);
3625 in->standby = 1;
3626 }
3627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003629 if (adev->adm_deregister_stream)
3630 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3631
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003632 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003634 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3635 voice_extn_compress_voip_close_input_stream(stream);
3636 ALOGD("VOIP input entered standby");
3637 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303638 if (audio_extn_cin_attached_usecase(in->usecase))
3639 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003640 if (in->pcm) {
3641 pcm_close(in->pcm);
3642 in->pcm = NULL;
3643 }
3644 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003645 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003646 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 }
3648 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003649 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 return status;
3651}
3652
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003653static int in_dump(const struct audio_stream *stream __unused,
3654 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655{
3656 return 0;
3657}
3658
3659static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3660{
3661 struct stream_in *in = (struct stream_in *)stream;
3662 struct audio_device *adev = in->dev;
3663 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003665 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303667 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668 parms = str_parms_create_str(kvpairs);
3669
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303670 if (!parms)
3671 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003672 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003673 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003674
3675 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3676 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 val = atoi(value);
3678 /* no audio source uses val == 0 */
3679 if ((in->source != val) && (val != 0)) {
3680 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003681 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3682 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3683 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003684 (in->config.rate == 8000 || in->config.rate == 16000 ||
3685 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003686 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003687 err = voice_extn_compress_voip_open_input_stream(in);
3688 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003689 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003690 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003691 }
3692 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 }
3694 }
3695
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003696 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3697 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003699 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 in->device = val;
3701 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003702 if (!in->standby && !in->is_st_session) {
3703 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003704 if (adev->adm_on_routing_change)
3705 adev->adm_on_routing_change(adev->adm_data,
3706 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003707 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 }
3710 }
3711
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303712 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3713 if (err >= 0) {
3714 strlcpy(in->profile, value, sizeof(in->profile));
3715 ALOGV("updating stream profile with value '%s'", in->profile);
3716 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3717 &adev->streams_input_cfg_list,
3718 in->device, in->flags, in->format,
3719 in->sample_rate, in->bit_width,
3720 in->profile, &in->app_type_cfg);
3721 }
3722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003724 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725
3726 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303727error:
Eric Laurent994a6932013-07-17 11:51:42 -07003728 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 return ret;
3730}
3731
3732static char* in_get_parameters(const struct audio_stream *stream,
3733 const char *keys)
3734{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003735 struct stream_in *in = (struct stream_in *)stream;
3736 struct str_parms *query = str_parms_create_str(keys);
3737 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003738 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003739
3740 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003741 if (reply) {
3742 str_parms_destroy(reply);
3743 }
3744 if (query) {
3745 str_parms_destroy(query);
3746 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003747 ALOGE("in_get_parameters: failed to create query or reply");
3748 return NULL;
3749 }
3750
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003751 ALOGV("%s: enter: keys - %s", __func__, keys);
3752
3753 voice_extn_in_get_parameters(in, query, reply);
3754
3755 str = str_parms_to_str(reply);
3756 str_parms_destroy(query);
3757 str_parms_destroy(reply);
3758
3759 ALOGV("%s: exit: returns - %s", __func__, str);
3760 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761}
3762
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003763static int in_set_gain(struct audio_stream_in *stream __unused,
3764 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765{
3766 return 0;
3767}
3768
3769static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3770 size_t bytes)
3771{
3772 struct stream_in *in = (struct stream_in *)stream;
3773 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303774 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303775 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303776 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003778 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303779
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003780 if (in->is_st_session) {
3781 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3782 /* Read from sound trigger HAL */
3783 audio_extn_sound_trigger_read(in, buffer, bytes);
3784 pthread_mutex_unlock(&in->lock);
3785 return bytes;
3786 }
3787
Ashish Jainbbce4322016-02-16 13:25:27 +05303788 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003789 ALOGD(" %s: sound card is not active/SSR state", __func__);
3790 ret= -EIO;;
3791 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303792 }
3793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003795 pthread_mutex_lock(&adev->lock);
3796 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3797 ret = voice_extn_compress_voip_start_input_stream(in);
3798 else
3799 ret = start_input_stream(in);
3800 pthread_mutex_unlock(&adev->lock);
3801 if (ret != 0) {
3802 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 }
3804 in->standby = 0;
3805 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003807 // what's the duration requested by the client?
3808 long ns = 0;
3809
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303810 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003811 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3812 in->config.rate;
3813
3814 request_in_focus(in, ns);
3815 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003816
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303817 if (audio_extn_cin_attached_usecase(in->usecase)) {
3818 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3819 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303820 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003821 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303822 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003823 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003824 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003825 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303826 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003827 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303828 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3829 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3830 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3831 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303832 ret = -EINVAL;
3833 goto exit;
3834 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303835 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303836 ret = -errno;
3837 }
3838 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303839 /* bytes read is always set to bytes for non compress usecases */
3840 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 }
3842
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003843 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845 /*
3846 * Instead of writing zeroes here, we could trust the hardware
3847 * to always provide zeroes when muted.
3848 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303849 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3850 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 memset(buffer, 0, bytes);
3852
3853exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303854 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303855 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003856 if (-ENETRESET == ret)
3857 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 pthread_mutex_unlock(&in->lock);
3860
3861 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303862 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303863 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303864 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303865 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303866 in->standby = true;
3867 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303868 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3869 bytes_read = bytes;
3870 memset(buffer, 0, bytes);
3871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003873 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303874 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303875 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303877 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878}
3879
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003880static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881{
3882 return 0;
3883}
3884
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003885static int add_remove_audio_effect(const struct audio_stream *stream,
3886 effect_handle_t effect,
3887 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003889 struct stream_in *in = (struct stream_in *)stream;
3890 int status = 0;
3891 effect_descriptor_t desc;
3892
3893 status = (*effect)->get_descriptor(effect, &desc);
3894 if (status != 0)
3895 return status;
3896
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003897 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003898 pthread_mutex_lock(&in->dev->lock);
3899 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3900 in->enable_aec != enable &&
3901 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3902 in->enable_aec = enable;
3903 if (!in->standby)
3904 select_devices(in->dev, in->usecase);
3905 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003906 if (in->enable_ns != enable &&
3907 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3908 in->enable_ns = enable;
3909 if (!in->standby)
3910 select_devices(in->dev, in->usecase);
3911 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003912 pthread_mutex_unlock(&in->dev->lock);
3913 pthread_mutex_unlock(&in->lock);
3914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 return 0;
3916}
3917
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003918static int in_add_audio_effect(const struct audio_stream *stream,
3919 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920{
Eric Laurent994a6932013-07-17 11:51:42 -07003921 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003922 return add_remove_audio_effect(stream, effect, true);
3923}
3924
3925static int in_remove_audio_effect(const struct audio_stream *stream,
3926 effect_handle_t effect)
3927{
Eric Laurent994a6932013-07-17 11:51:42 -07003928 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003929 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930}
3931
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303932int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933 audio_io_handle_t handle,
3934 audio_devices_t devices,
3935 audio_output_flags_t flags,
3936 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003937 struct audio_stream_out **stream_out,
3938 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939{
3940 struct audio_device *adev = (struct audio_device *)dev;
3941 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303942 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003943 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003944 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303947
3948 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3949 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003950 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303951 return -EINVAL;
3952 }
3953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3955
Mingming Yin3a941d42016-02-17 18:08:05 -08003956 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3957 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303958 devices, flags, &out->stream);
3959
3960
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003961 if (!out) {
3962 return -ENOMEM;
3963 }
3964
Haynes Mathew George204045b2015-02-25 20:32:03 -08003965 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003966 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003967 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969 if (devices == AUDIO_DEVICE_NONE)
3970 devices = AUDIO_DEVICE_OUT_SPEAKER;
3971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 out->flags = flags;
3973 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003974 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003975 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976 out->sample_rate = config->sample_rate;
3977 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3978 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003979 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003980 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003981 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303982 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983
Mingming Yin3a941d42016-02-17 18:08:05 -08003984 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3985 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3986 pthread_mutex_lock(&adev->lock);
3987 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3988 ret = read_hdmi_sink_caps(out);
3989 pthread_mutex_unlock(&adev->lock);
3990 if (ret != 0) {
3991 if (ret == -ENOSYS) {
3992 /* ignore and go with default */
3993 ret = 0;
3994 } else {
3995 ALOGE("error reading hdmi sink caps");
3996 goto error_open;
3997 }
3998 }
3999 }
4000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004001 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304002 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004003 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004004 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004005 ret = voice_extn_compress_voip_open_output_stream(out);
4006 if (ret != 0) {
4007 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4008 __func__, ret);
4009 goto error_open;
4010 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004011 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304012 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004013
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004014 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4015 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4016 ALOGE("%s: Unsupported Offload information", __func__);
4017 ret = -EINVAL;
4018 goto error_open;
4019 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004020
Mingming Yin3a941d42016-02-17 18:08:05 -08004021 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004022 if(config->offload_info.format == 0)
4023 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004024 if (config->offload_info.sample_rate == 0)
4025 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004026 }
4027
Mingming Yin90310102013-11-13 16:57:00 -08004028 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304029 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004030 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004031 ret = -EINVAL;
4032 goto error_open;
4033 }
4034
4035 out->compr_config.codec = (struct snd_codec *)
4036 calloc(1, sizeof(struct snd_codec));
4037
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004038 if (!out->compr_config.codec) {
4039 ret = -ENOMEM;
4040 goto error_open;
4041 }
4042
Dhananjay Kumarac341582017-02-23 23:42:25 +05304043 out->stream.pause = out_pause;
4044 out->stream.resume = out_resume;
4045 out->stream.flush = out_flush;
4046 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004047 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004048 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304049 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004050 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304051 } else {
4052 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4053 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004054 }
vivek mehta446c3962015-09-14 10:57:35 -07004055
4056 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004057 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4058 config->format == 0 && config->sample_rate == 0 &&
4059 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004060 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004061 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4062 } else {
4063 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4064 ret = -EEXIST;
4065 goto error_open;
4066 }
vivek mehta446c3962015-09-14 10:57:35 -07004067 }
4068
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004069 if (config->offload_info.channel_mask)
4070 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004071 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004073 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004074 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304075 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004076 ret = -EINVAL;
4077 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004078 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004079
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004080 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004081 out->sample_rate = config->offload_info.sample_rate;
4082
Mingming Yin3ee55c62014-08-04 14:23:35 -07004083 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304085 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4086 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4087 audio_extn_dolby_send_ddp_endp_params(adev);
4088 audio_extn_dolby_set_dmid(adev);
4089 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004090
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004091 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004092 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004093 out->compr_config.codec->bit_rate =
4094 config->offload_info.bit_rate;
4095 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304096 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004097 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304098 /* Update bit width only for non passthrough usecases.
4099 * For passthrough usecases, the output will always be opened @16 bit
4100 */
4101 if (!audio_extn_passthru_is_passthrough_stream(out))
4102 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304103
4104 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4105 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4106 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4107
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004108 /*TODO: Do we need to change it for passthrough */
4109 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004110
Manish Dewangana6fc5442015-08-24 20:30:31 +05304111 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4112 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304113 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304114 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304115 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4116 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304117
4118 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4119 AUDIO_FORMAT_PCM) {
4120
4121 /*Based on platform support, configure appropriate alsa format for corresponding
4122 *hal input format.
4123 */
4124 out->compr_config.codec->format = hal_format_to_alsa(
4125 config->offload_info.format);
4126
Ashish Jain83a6cc22016-06-28 14:34:17 +05304127 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304128 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304129 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304130
Dhananjay Kumarac341582017-02-23 23:42:25 +05304131 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304132 *hal input format and alsa format might differ based on platform support.
4133 */
4134 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304135 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304136
4137 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4138
4139 /* Check if alsa session is configured with the same format as HAL input format,
4140 * if not then derive correct fragment size needed to accomodate the
4141 * conversion of HAL input format to alsa format.
4142 */
4143 audio_extn_utils_update_direct_pcm_fragment_size(out);
4144
4145 /*if hal input and output fragment size is different this indicates HAL input format is
4146 *not same as the alsa format
4147 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304148 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304149 /*Allocate a buffer to convert input data to the alsa configured format.
4150 *size of convert buffer is equal to the size required to hold one fragment size
4151 *worth of pcm data, this is because flinger does not write more than fragment_size
4152 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304153 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4154 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304155 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4156 ret = -ENOMEM;
4157 goto error_open;
4158 }
4159 }
4160 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4161 out->compr_config.fragment_size =
4162 audio_extn_passthru_get_buffer_size(&config->offload_info);
4163 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4164 } else {
4165 out->compr_config.fragment_size =
4166 platform_get_compress_offload_buffer_size(&config->offload_info);
4167 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4168 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004169
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304170 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4171 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4172 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004173 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304174 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004175
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304176 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4177 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4178 }
4179
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004180 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4181 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004182
Manish Dewangan69426c82017-01-30 17:35:36 +05304183 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4184 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4185 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4186 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4187 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4188 } else {
4189 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4190 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004191
Manish Dewangan27346042017-03-01 12:56:12 +05304192 memset(&out->render_window, 0,
4193 sizeof(struct audio_out_render_window_param));
4194
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004195 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304196 out->send_next_track_params = false;
4197 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004198 out->offload_state = OFFLOAD_STATE_IDLE;
4199 out->playback_started = 0;
4200
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004201 audio_extn_dts_create_state_notifier_node(out->usecase);
4202
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004203 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4204 __func__, config->offload_info.version,
4205 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304206
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304207 /* Check if DSD audio format is supported in codec
4208 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304209 */
4210
4211 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304212 (!platform_check_codec_dsd_support(adev->platform) ||
4213 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304214 ret = -EINVAL;
4215 goto error_open;
4216 }
4217
Ashish Jain5106d362016-05-11 19:23:33 +05304218 /* Disable gapless if any of the following is true
4219 * passthrough playback
4220 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304221 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304222 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304223 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304224 (config->format == AUDIO_FORMAT_DSD) ||
4225 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304226 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304227 check_and_set_gapless_mode(adev, false);
4228 } else
4229 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004230
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304231 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004232 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4233 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304234 if (config->format == AUDIO_FORMAT_DSD) {
4235 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4236 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4237 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004238
4239 create_offload_callback_thread(out);
4240
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004241 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304242 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004243 if (ret != 0) {
4244 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4245 __func__, ret);
4246 goto error_open;
4247 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004248 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4249 if (config->sample_rate == 0)
4250 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4251 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4252 config->sample_rate != 8000) {
4253 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4254 ret = -EINVAL;
4255 goto error_open;
4256 }
4257 out->sample_rate = config->sample_rate;
4258 out->config.rate = config->sample_rate;
4259 if (config->format == AUDIO_FORMAT_DEFAULT)
4260 config->format = AUDIO_FORMAT_PCM_16_BIT;
4261 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4262 config->format = AUDIO_FORMAT_PCM_16_BIT;
4263 ret = -EINVAL;
4264 goto error_open;
4265 }
4266 out->format = config->format;
4267 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4268 out->config = pcm_config_afe_proxy_playback;
4269 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004270 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304271 unsigned int channels = 0;
4272 /*Update config params to default if not set by the caller*/
4273 if (config->sample_rate == 0)
4274 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4275 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4276 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4277 if (config->format == AUDIO_FORMAT_DEFAULT)
4278 config->format = AUDIO_FORMAT_PCM_16_BIT;
4279
4280 channels = audio_channel_count_from_out_mask(out->channel_mask);
4281
Ashish Jain83a6cc22016-06-28 14:34:17 +05304282 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4283 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004284 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4285 out->flags);
4286 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304287 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4288 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4289 out->config = pcm_config_low_latency;
4290 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4291 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4292 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304293 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4294 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4295 if (out->config.period_size <= 0) {
4296 ALOGE("Invalid configuration period size is not valid");
4297 ret = -EINVAL;
4298 goto error_open;
4299 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304300 } else {
4301 /* primary path is the default path selected if no other outputs are available/suitable */
4302 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4303 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4304 }
4305 out->hal_ip_format = format = out->format;
4306 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4307 out->hal_op_format = pcm_format_to_hal(out->config.format);
4308 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4309 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004310 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304311 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304312 if (out->hal_ip_format != out->hal_op_format) {
4313 uint32_t buffer_size = out->config.period_size *
4314 format_to_bitwidth_table[out->hal_op_format] *
4315 out->config.channels;
4316 out->convert_buffer = calloc(1, buffer_size);
4317 if (out->convert_buffer == NULL){
4318 ALOGE("Allocation failed for convert buffer for size %d",
4319 out->compr_config.fragment_size);
4320 ret = -ENOMEM;
4321 goto error_open;
4322 }
4323 ALOGD("Convert buffer allocated of size %d", buffer_size);
4324 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 }
4326
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004327 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4328 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304329
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004330 /* TODO remove this hardcoding and check why width is zero*/
4331 if (out->bit_width == 0)
4332 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304333 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004334 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304335 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304336 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304337 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004338 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4339 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4340 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004341 if(adev->primary_output == NULL)
4342 adev->primary_output = out;
4343 else {
4344 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004345 ret = -EEXIST;
4346 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004347 }
4348 }
4349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350 /* Check if this usecase is already existing */
4351 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004352 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4353 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004356 ret = -EEXIST;
4357 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 pthread_mutex_unlock(&adev->lock);
4361
4362 out->stream.common.get_sample_rate = out_get_sample_rate;
4363 out->stream.common.set_sample_rate = out_set_sample_rate;
4364 out->stream.common.get_buffer_size = out_get_buffer_size;
4365 out->stream.common.get_channels = out_get_channels;
4366 out->stream.common.get_format = out_get_format;
4367 out->stream.common.set_format = out_set_format;
4368 out->stream.common.standby = out_standby;
4369 out->stream.common.dump = out_dump;
4370 out->stream.common.set_parameters = out_set_parameters;
4371 out->stream.common.get_parameters = out_get_parameters;
4372 out->stream.common.add_audio_effect = out_add_audio_effect;
4373 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4374 out->stream.get_latency = out_get_latency;
4375 out->stream.set_volume = out_set_volume;
4376 out->stream.write = out_write;
4377 out->stream.get_render_position = out_get_render_position;
4378 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004379 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004381 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004383 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004384 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385
4386 config->format = out->stream.common.get_format(&out->stream.common);
4387 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4388 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4389
4390 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304391 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004392 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004393
4394 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4395 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4396 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004397 /* setup a channel for client <--> adsp communication for stream events */
4398 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
4399 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
4400 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4401 out->usecase, PCM_PLAYBACK);
4402 hdlr_stream_cfg.flags = out->flags;
4403 hdlr_stream_cfg.type = PCM_PLAYBACK;
4404 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4405 &hdlr_stream_cfg);
4406 if (ret) {
4407 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4408 out->adsp_hdlr_stream_handle = NULL;
4409 }
4410 }
Eric Laurent994a6932013-07-17 11:51:42 -07004411 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004413
4414error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304415 if (out->convert_buffer)
4416 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004417 free(out);
4418 *stream_out = NULL;
4419 ALOGD("%s: exit: ret %d", __func__, ret);
4420 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421}
4422
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304423void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424 struct audio_stream_out *stream)
4425{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004426 struct stream_out *out = (struct stream_out *)stream;
4427 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004428 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004429
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304430 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4431
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004432 /* close adsp hdrl session before standby */
4433 if (out->adsp_hdlr_stream_handle) {
4434 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4435 if (ret)
4436 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4437 out->adsp_hdlr_stream_handle = NULL;
4438 }
4439
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004440 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304441 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004442 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304443 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004444 if(ret != 0)
4445 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4446 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004447 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004448 out_standby(&stream->common);
4449
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004450 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004451 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004452 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004453 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004454 if (out->compr_config.codec != NULL)
4455 free(out->compr_config.codec);
4456 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004457
Ashish Jain83a6cc22016-06-28 14:34:17 +05304458 if (out->convert_buffer != NULL) {
4459 free(out->convert_buffer);
4460 out->convert_buffer = NULL;
4461 }
4462
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004463 if (adev->voice_tx_output == out)
4464 adev->voice_tx_output = NULL;
4465
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304466 if (adev->primary_output == out)
4467 adev->primary_output = NULL;
4468
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004469 pthread_cond_destroy(&out->cond);
4470 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004472 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473}
4474
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004475static void close_compress_sessions(struct audio_device *adev)
4476{
Mingming Yin7b762e72015-03-04 13:47:32 -08004477 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304478 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004479 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004480 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304481
4482 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004483 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304484 if (is_offload_usecase(usecase->id)) {
4485 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004486 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4487 out = usecase->stream.out;
4488 pthread_mutex_unlock(&adev->lock);
4489 out_standby(&out->stream.common);
4490 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004491 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004492 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304493 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004494 }
4495 pthread_mutex_unlock(&adev->lock);
4496}
4497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4499{
4500 struct audio_device *adev = (struct audio_device *)dev;
4501 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004503 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004504 int ret;
4505 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004507 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304510 if (!parms)
4511 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004512 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4513 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304514 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304515 if (strstr(snd_card_status, "OFFLINE")) {
4516 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304517 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004518 //close compress sessions on OFFLINE status
4519 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304520 } else if (strstr(snd_card_status, "ONLINE")) {
4521 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304522 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004523 //send dts hpx license if enabled
4524 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304525 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304526 }
4527
4528 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004529 status = voice_set_parameters(adev, parms);
4530 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004531 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004533 status = platform_set_parameters(adev->platform, parms);
4534 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004535 goto done;
4536
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004537 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4538 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004539 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4541 adev->bluetooth_nrec = true;
4542 else
4543 adev->bluetooth_nrec = false;
4544 }
4545
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004546 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4547 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4549 adev->screen_off = false;
4550 else
4551 adev->screen_off = true;
4552 }
4553
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004554 ret = str_parms_get_int(parms, "rotation", &val);
4555 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004556 bool reverse_speakers = false;
4557 switch(val) {
4558 // FIXME: note that the code below assumes that the speakers are in the correct placement
4559 // relative to the user when the device is rotated 90deg from its default rotation. This
4560 // assumption is device-specific, not platform-specific like this code.
4561 case 270:
4562 reverse_speakers = true;
4563 break;
4564 case 0:
4565 case 90:
4566 case 180:
4567 break;
4568 default:
4569 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004570 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004571 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004572 if (status == 0) {
4573 if (adev->speaker_lr_swap != reverse_speakers) {
4574 adev->speaker_lr_swap = reverse_speakers;
4575 // only update the selected device if there is active pcm playback
4576 struct audio_usecase *usecase;
4577 struct listnode *node;
4578 list_for_each(node, &adev->usecase_list) {
4579 usecase = node_to_item(node, struct audio_usecase, list);
4580 if (usecase->type == PCM_PLAYBACK) {
4581 select_devices(adev, usecase->id);
4582 break;
4583 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004584 }
4585 }
4586 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004587 }
4588
Mingming Yin514a8bc2014-07-29 15:22:21 -07004589 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4590 if (ret >= 0) {
4591 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4592 adev->bt_wb_speech_enabled = true;
4593 else
4594 adev->bt_wb_speech_enabled = false;
4595 }
4596
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004597 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4598 if (ret >= 0) {
4599 val = atoi(value);
4600 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004601 ALOGV("cache new ext disp type and edid");
4602 ret = platform_get_ext_disp_type(adev->platform);
4603 if (ret < 0) {
4604 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004605 status = ret;
4606 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004607 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004608 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004609 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004610 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004611 /*
4612 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4613 * Per AudioPolicyManager, USB device is higher priority than WFD.
4614 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4615 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4616 * starting voice call on USB
4617 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004618 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4619 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004620 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4621 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004622 }
vivek mehta344576a2016-04-12 18:56:03 -07004623 ALOGV("detected USB connect .. disable proxy");
4624 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004625 }
4626 }
4627
4628 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4629 if (ret >= 0) {
4630 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004631 /*
4632 * The HDMI / Displayport disconnect handling has been moved to
4633 * audio extension to ensure that its parameters are not
4634 * invalidated prior to updating sysfs of the disconnect event
4635 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4636 */
4637 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004638 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004639 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4640 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304641 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4642 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004643 }
vivek mehta344576a2016-04-12 18:56:03 -07004644 ALOGV("detected USB disconnect .. enable proxy");
4645 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004646 }
4647 }
4648
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304649 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4650 if (ret >= 0) {
4651 struct audio_usecase *usecase;
4652 struct listnode *node;
4653 list_for_each(node, &adev->usecase_list) {
4654 usecase = node_to_item(node, struct audio_usecase, list);
4655 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004656 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304657 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304658 lock_output_stream(usecase->stream.out);
4659 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304660 //force device switch to re configure encoder
4661 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304662 audio_extn_a2dp_set_handoff_mode(false);
4663 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304664 break;
4665 }
4666 }
4667 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004668
4669 //handle vr audio setparam
4670 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4671 value, sizeof(value));
4672 if (ret >= 0) {
4673 ALOGI("Setting vr mode to be %s", value);
4674 if (!strncmp(value, "true", 4)) {
4675 adev->vr_audio_mode_enabled = true;
4676 ALOGI("Setting vr mode to true");
4677 } else if (!strncmp(value, "false", 5)) {
4678 adev->vr_audio_mode_enabled = false;
4679 ALOGI("Setting vr mode to false");
4680 } else {
4681 ALOGI("wrong vr mode set");
4682 }
4683 }
4684
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304685 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004686done:
4687 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004688 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304689error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004690 ALOGV("%s: exit with code(%d)", __func__, status);
4691 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692}
4693
4694static char* adev_get_parameters(const struct audio_hw_device *dev,
4695 const char *keys)
4696{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004697 struct audio_device *adev = (struct audio_device *)dev;
4698 struct str_parms *reply = str_parms_create();
4699 struct str_parms *query = str_parms_create_str(keys);
4700 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304701 char value[256] = {0};
4702 int ret = 0;
4703
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004704 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004705 if (reply) {
4706 str_parms_destroy(reply);
4707 }
4708 if (query) {
4709 str_parms_destroy(query);
4710 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004711 ALOGE("adev_get_parameters: failed to create query or reply");
4712 return NULL;
4713 }
4714
Naresh Tannirud7205b62014-06-20 02:54:48 +05304715 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4716 sizeof(value));
4717 if (ret >=0) {
4718 int val = 1;
4719 pthread_mutex_lock(&adev->snd_card_status.lock);
4720 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4721 val = 0;
4722 pthread_mutex_unlock(&adev->snd_card_status.lock);
4723 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4724 goto exit;
4725 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004726 //handle vr audio getparam
4727
4728 ret = str_parms_get_str(query,
4729 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4730 value, sizeof(value));
4731
4732 if (ret >= 0) {
4733 bool vr_audio_enabled = false;
4734 pthread_mutex_lock(&adev->lock);
4735 vr_audio_enabled = adev->vr_audio_mode_enabled;
4736 pthread_mutex_unlock(&adev->lock);
4737
4738 ALOGI("getting vr mode to %d", vr_audio_enabled);
4739
4740 if (vr_audio_enabled) {
4741 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4742 "true");
4743 goto exit;
4744 } else {
4745 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4746 "false");
4747 goto exit;
4748 }
4749 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004750
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004751 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004752 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004753 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004754 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304755 pthread_mutex_unlock(&adev->lock);
4756
Naresh Tannirud7205b62014-06-20 02:54:48 +05304757exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004758 str = str_parms_to_str(reply);
4759 str_parms_destroy(query);
4760 str_parms_destroy(reply);
4761
4762 ALOGV("%s: exit: returns - %s", __func__, str);
4763 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004764}
4765
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004766static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767{
4768 return 0;
4769}
4770
4771static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4772{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004773 int ret;
4774 struct audio_device *adev = (struct audio_device *)dev;
4775 pthread_mutex_lock(&adev->lock);
4776 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004777 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004778 pthread_mutex_unlock(&adev->lock);
4779 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780}
4781
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004782static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4783 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784{
4785 return -ENOSYS;
4786}
4787
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004788static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4789 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790{
4791 return -ENOSYS;
4792}
4793
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004794static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4795 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796{
4797 return -ENOSYS;
4798}
4799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004800static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4801 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802{
4803 return -ENOSYS;
4804}
4805
4806static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4807{
4808 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004810 pthread_mutex_lock(&adev->lock);
4811 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004812 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004813 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004814 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004815 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004816 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004817 adev->current_call_output = NULL;
4818 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819 }
4820 pthread_mutex_unlock(&adev->lock);
4821 return 0;
4822}
4823
4824static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4825{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004826 int ret;
4827
4828 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004829 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004830 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4831 pthread_mutex_unlock(&adev->lock);
4832
4833 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834}
4835
4836static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4837{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004838 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004839 return 0;
4840}
4841
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004842static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004843 const struct audio_config *config)
4844{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004845 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004846
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004847 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4848 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849}
4850
4851static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004852 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853 audio_devices_t devices,
4854 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004855 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304856 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004857 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004858 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859{
4860 struct audio_device *adev = (struct audio_device *)dev;
4861 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004862 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004863 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004864 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304865 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004867 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304868 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4869 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004872
4873 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004874
4875 if (!in) {
4876 ALOGE("failed to allocate input stream");
4877 return -ENOMEM;
4878 }
4879
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304880 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304881 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4882 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004883 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004884 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886 in->stream.common.get_sample_rate = in_get_sample_rate;
4887 in->stream.common.set_sample_rate = in_set_sample_rate;
4888 in->stream.common.get_buffer_size = in_get_buffer_size;
4889 in->stream.common.get_channels = in_get_channels;
4890 in->stream.common.get_format = in_get_format;
4891 in->stream.common.set_format = in_set_format;
4892 in->stream.common.standby = in_standby;
4893 in->stream.common.dump = in_dump;
4894 in->stream.common.set_parameters = in_set_parameters;
4895 in->stream.common.get_parameters = in_get_parameters;
4896 in->stream.common.add_audio_effect = in_add_audio_effect;
4897 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4898 in->stream.set_gain = in_set_gain;
4899 in->stream.read = in_read;
4900 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4901
4902 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004903 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004904 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004905 in->standby = 1;
4906 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004907 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004908 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004909
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304910 in->usecase = USECASE_AUDIO_RECORD;
4911 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4912 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4913 is_low_latency = true;
4914#if LOW_LATENCY_CAPTURE_USE_CASE
4915 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4916#endif
4917 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4918 }
4919
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004920 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004921 if (in->realtime) {
4922 in->config = pcm_config_audio_capture_rt;
4923 in->sample_rate = in->config.rate;
4924 in->af_period_multiplier = af_period_multiplier;
4925 } else {
4926 in->config = pcm_config_audio_capture;
4927 in->config.rate = config->sample_rate;
4928 in->sample_rate = config->sample_rate;
4929 in->af_period_multiplier = 1;
4930 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304931 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004932
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304933 /* restrict 24 bit capture for unprocessed source only
4934 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4935 */
4936 if (config->format == AUDIO_FORMAT_DEFAULT) {
4937 config->format = AUDIO_FORMAT_PCM_16_BIT;
4938 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4939 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4940 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4941 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4942 bool ret_error = false;
4943 in->bit_width = 24;
4944 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4945 from HAL is 24_packed and 8_24
4946 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4947 24_packed return error indicating supported format is 24_packed
4948 *> In case of any other source requesting 24 bit or float return error
4949 indicating format supported is 16 bit only.
4950
4951 on error flinger will retry with supported format passed
4952 */
4953 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4954 (source != AUDIO_SOURCE_CAMCORDER)) {
4955 config->format = AUDIO_FORMAT_PCM_16_BIT;
4956 if (config->sample_rate > 48000)
4957 config->sample_rate = 48000;
4958 ret_error = true;
4959 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4960 in->config.format = PCM_FORMAT_S24_3LE;
4961 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4962 in->config.format = PCM_FORMAT_S24_LE;
4963 } else {
4964 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4965 ret_error = true;
4966 }
4967
4968 if (ret_error) {
4969 ret = -EINVAL;
4970 goto err_open;
4971 }
4972 }
4973
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304974 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304975 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4976 (adev->mode != AUDIO_MODE_IN_CALL)) {
4977 ret = -EINVAL;
4978 goto err_open;
4979 }
4980
4981 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4982 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004983 if (config->sample_rate == 0)
4984 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4985 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4986 config->sample_rate != 8000) {
4987 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4988 ret = -EINVAL;
4989 goto err_open;
4990 }
4991 if (config->format == AUDIO_FORMAT_DEFAULT)
4992 config->format = AUDIO_FORMAT_PCM_16_BIT;
4993 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4994 config->format = AUDIO_FORMAT_PCM_16_BIT;
4995 ret = -EINVAL;
4996 goto err_open;
4997 }
4998
4999 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5000 in->config = pcm_config_afe_proxy_record;
5001 in->config.channels = channel_count;
5002 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305003 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305004 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5005 in, config, &channel_mask_updated)) {
5006 if (channel_mask_updated == true) {
5007 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5008 __func__, config->channel_mask);
5009 ret = -EINVAL;
5010 goto err_open;
5011 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305012 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005013 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005014 audio_extn_compr_cap_format_supported(config->format) &&
5015 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005016 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305017 } else if (audio_extn_cin_applicable_stream(in)) {
5018 ret = audio_extn_cin_configure_input_stream(in);
5019 if (ret)
5020 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005021 } else {
5022 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005023 if (!in->realtime) {
5024 in->format = config->format;
5025 frame_size = audio_stream_in_frame_size(&in->stream);
5026 buffer_size = get_input_buffer_size(config->sample_rate,
5027 config->format,
5028 channel_count,
5029 is_low_latency);
5030 in->config.period_size = buffer_size / frame_size;
5031 }
5032
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005033 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005034 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005035 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005036 (in->config.rate == 8000 || in->config.rate == 16000 ||
5037 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005038 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5039 voice_extn_compress_voip_open_input_stream(in);
5040 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005041 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005042
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305043 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5044 &adev->streams_input_cfg_list,
5045 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305046 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305047
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005048 /* This stream could be for sound trigger lab,
5049 get sound trigger pcm if present */
5050 audio_extn_sound_trigger_check_and_get_session(in);
5051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005052 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005053 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005054 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055
5056err_open:
5057 free(in);
5058 *stream_in = NULL;
5059 return ret;
5060}
5061
5062static void adev_close_input_stream(struct audio_hw_device *dev,
5063 struct audio_stream_in *stream)
5064{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005065 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005066 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005067 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305068
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305069 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005070
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305071 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005072 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005074 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305075 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005076 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305077 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005078 if (ret != 0)
5079 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5080 __func__, ret);
5081 } else
5082 in_standby(&stream->common);
5083
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005084 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005085 audio_extn_ssr_deinit();
5086 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305088 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005089 audio_extn_compr_cap_format_supported(in->config.format))
5090 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305091
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305092 if (audio_extn_cin_attached_usecase(in->usecase))
5093 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005094
Mingming Yinfd7607b2016-01-22 12:48:44 -08005095 if (in->is_st_session) {
5096 ALOGV("%s: sound trigger pcm stop lab", __func__);
5097 audio_extn_sound_trigger_stop_lab(in);
5098 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005099 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100 return;
5101}
5102
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005103static int adev_dump(const audio_hw_device_t *device __unused,
5104 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005105{
5106 return 0;
5107}
5108
5109static int adev_close(hw_device_t *device)
5110{
5111 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005112
5113 if (!adev)
5114 return 0;
5115
5116 pthread_mutex_lock(&adev_init_lock);
5117
5118 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005119 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005120 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305121 audio_extn_utils_release_streams_cfg_lists(
5122 &adev->streams_output_cfg_list,
5123 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305124 if (audio_extn_qaf_is_enabled())
5125 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005126 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005127 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005128 free(adev->snd_dev_ref_cnt);
5129 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005130 if (adev->adm_deinit)
5131 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305132 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005133 audio_extn_adsp_hdlr_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005134 free(device);
5135 adev = NULL;
5136 }
5137 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005139 return 0;
5140}
5141
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005142/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5143 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5144 * just that it _might_ work.
5145 */
5146static int period_size_is_plausible_for_low_latency(int period_size)
5147{
5148 switch (period_size) {
5149 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005150 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005151 case 240:
5152 case 320:
5153 case 480:
5154 return 1;
5155 default:
5156 return 0;
5157 }
5158}
5159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160static int adev_open(const hw_module_t *module, const char *name,
5161 hw_device_t **device)
5162{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305163 int ret;
5164
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005165 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005166 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5167
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005168 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005169 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005170 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005171 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005172 ALOGD("%s: returning existing instance of adev", __func__);
5173 ALOGD("%s: exit", __func__);
5174 pthread_mutex_unlock(&adev_init_lock);
5175 return 0;
5176 }
5177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178 adev = calloc(1, sizeof(struct audio_device));
5179
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005180 if (!adev) {
5181 pthread_mutex_unlock(&adev_init_lock);
5182 return -ENOMEM;
5183 }
5184
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005185 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005187 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5188 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5189 adev->device.common.module = (struct hw_module_t *)module;
5190 adev->device.common.close = adev_close;
5191
5192 adev->device.init_check = adev_init_check;
5193 adev->device.set_voice_volume = adev_set_voice_volume;
5194 adev->device.set_master_volume = adev_set_master_volume;
5195 adev->device.get_master_volume = adev_get_master_volume;
5196 adev->device.set_master_mute = adev_set_master_mute;
5197 adev->device.get_master_mute = adev_get_master_mute;
5198 adev->device.set_mode = adev_set_mode;
5199 adev->device.set_mic_mute = adev_set_mic_mute;
5200 adev->device.get_mic_mute = adev_get_mic_mute;
5201 adev->device.set_parameters = adev_set_parameters;
5202 adev->device.get_parameters = adev_get_parameters;
5203 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5204 adev->device.open_output_stream = adev_open_output_stream;
5205 adev->device.close_output_stream = adev_close_output_stream;
5206 adev->device.open_input_stream = adev_open_input_stream;
5207 adev->device.close_input_stream = adev_close_input_stream;
5208 adev->device.dump = adev_dump;
5209
5210 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005212 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005213 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005215 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005216 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005217 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005218 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005219 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005220 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005221 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005222 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005223 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305224 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305225 adev->perf_lock_opts[0] = 0x101;
5226 adev->perf_lock_opts[1] = 0x20E;
5227 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305228
5229 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5230 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005232 adev->platform = platform_init(adev);
5233 if (!adev->platform) {
5234 free(adev->snd_dev_ref_cnt);
5235 free(adev);
5236 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5237 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005238 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305239 pthread_mutex_destroy(&adev->lock);
5240 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005241 return -EINVAL;
5242 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005243
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305244 if (audio_extn_qaf_is_enabled()) {
5245 ret = audio_extn_qaf_init(adev);
5246 if (ret < 0) {
5247 free(adev);
5248 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5249 *device = NULL;
5250 pthread_mutex_unlock(&adev_init_lock);
5251 pthread_mutex_destroy(&adev->lock);
5252 return ret;
5253 }
5254
5255 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5256 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5257 }
5258
Naresh Tanniru4c630392014-05-12 01:05:52 +05305259 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5260
Eric Laurentc4aef752013-09-12 17:45:53 -07005261 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5262 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5263 if (adev->visualizer_lib == NULL) {
5264 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5265 } else {
5266 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5267 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005268 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005269 "visualizer_hal_start_output");
5270 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005271 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005272 "visualizer_hal_stop_output");
5273 }
5274 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305275 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005276 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005277 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005278 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005279
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005280 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5281 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5282 if (adev->offload_effects_lib == NULL) {
5283 ALOGE("%s: DLOPEN failed for %s", __func__,
5284 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5285 } else {
5286 ALOGV("%s: DLOPEN successful for %s", __func__,
5287 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5288 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305289 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005290 "offload_effects_bundle_hal_start_output");
5291 adev->offload_effects_stop_output =
5292 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5293 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005294 adev->offload_effects_set_hpx_state =
5295 (int (*)(bool))dlsym(adev->offload_effects_lib,
5296 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305297 adev->offload_effects_get_parameters =
5298 (void (*)(struct str_parms *, struct str_parms *))
5299 dlsym(adev->offload_effects_lib,
5300 "offload_effects_bundle_get_parameters");
5301 adev->offload_effects_set_parameters =
5302 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5303 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005304 }
5305 }
5306
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005307 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5308 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5309 if (adev->adm_lib == NULL) {
5310 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5311 } else {
5312 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5313 adev->adm_init = (adm_init_t)
5314 dlsym(adev->adm_lib, "adm_init");
5315 adev->adm_deinit = (adm_deinit_t)
5316 dlsym(adev->adm_lib, "adm_deinit");
5317 adev->adm_register_input_stream = (adm_register_input_stream_t)
5318 dlsym(adev->adm_lib, "adm_register_input_stream");
5319 adev->adm_register_output_stream = (adm_register_output_stream_t)
5320 dlsym(adev->adm_lib, "adm_register_output_stream");
5321 adev->adm_deregister_stream = (adm_deregister_stream_t)
5322 dlsym(adev->adm_lib, "adm_deregister_stream");
5323 adev->adm_request_focus = (adm_request_focus_t)
5324 dlsym(adev->adm_lib, "adm_request_focus");
5325 adev->adm_abandon_focus = (adm_abandon_focus_t)
5326 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005327 adev->adm_set_config = (adm_set_config_t)
5328 dlsym(adev->adm_lib, "adm_set_config");
5329 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5330 dlsym(adev->adm_lib, "adm_request_focus_v2");
5331 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5332 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5333 adev->adm_on_routing_change = (adm_on_routing_change_t)
5334 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005335 }
5336 }
5337
Mingming Yin514a8bc2014-07-29 15:22:21 -07005338 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005339 //initialize this to false for now,
5340 //this will be set to true through set param
5341 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005342
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005343 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005344 *device = &adev->device.common;
5345
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305346 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5347 &adev->streams_output_cfg_list,
5348 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005349
Kiran Kandi910e1862013-10-29 13:29:42 -07005350 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005351
5352 char value[PROPERTY_VALUE_MAX];
5353 int trial;
5354 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5355 trial = atoi(value);
5356 if (period_size_is_plausible_for_low_latency(trial)) {
5357 pcm_config_low_latency.period_size = trial;
5358 pcm_config_low_latency.start_threshold = trial / 4;
5359 pcm_config_low_latency.avail_min = trial / 4;
5360 configured_low_latency_capture_period_size = trial;
5361 }
5362 }
5363 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5364 trial = atoi(value);
5365 if (period_size_is_plausible_for_low_latency(trial)) {
5366 configured_low_latency_capture_period_size = trial;
5367 }
5368 }
5369
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005370 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5371 af_period_multiplier = atoi(value);
5372 if (af_period_multiplier < 0)
5373 af_period_multiplier = 2;
5374 else if (af_period_multiplier > 4)
5375 af_period_multiplier = 4;
5376
5377 ALOGV("new period_multiplier = %d", af_period_multiplier);
5378 }
5379
vivek mehta446c3962015-09-14 10:57:35 -07005380 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005381 pthread_mutex_unlock(&adev_init_lock);
5382
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005383 if (adev->adm_init)
5384 adev->adm_data = adev->adm_init();
5385
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305386 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305387 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005388 audio_extn_adsp_hdlr_init(adev->mixer);
Eric Laurent994a6932013-07-17 11:51:42 -07005389 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005390 return 0;
5391}
5392
5393static struct hw_module_methods_t hal_module_methods = {
5394 .open = adev_open,
5395};
5396
5397struct audio_module HAL_MODULE_INFO_SYM = {
5398 .common = {
5399 .tag = HARDWARE_MODULE_TAG,
5400 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5401 .hal_api_version = HARDWARE_HAL_API_VERSION,
5402 .id = AUDIO_HARDWARE_MODULE_ID,
5403 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005404 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005405 .methods = &hal_module_methods,
5406 },
5407};