blob: 1013332b6a471f5bcc41fbfbea7b7a35bb6da022 [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
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053079#ifdef DYNAMIC_LOG_ENABLED
80#include <log_xml_parser.h>
81#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
82#include <log_utils.h>
83#endif
84
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070085#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053086/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
87#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053089#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070091#define PROXY_OPEN_RETRY_COUNT 100
92#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080093
Mingming Yin08c7e312015-03-16 18:10:58 -070094#ifdef USE_LL_AS_PRIMARY_OUTPUT
95#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
96#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
97#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080098#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070099#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
100#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800101
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700102#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
103
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700104static unsigned int configured_low_latency_capture_period_size =
105 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
106
Eric Laurentb23d5282013-05-14 15:27:20 -0700107struct pcm_config pcm_config_deep_buffer = {
108 .channels = 2,
109 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
110 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
111 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
114 .stop_threshold = INT_MAX,
115 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
116};
117
118struct pcm_config pcm_config_low_latency = {
119 .channels = 2,
120 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
121 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
122 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
123 .format = PCM_FORMAT_S16_LE,
124 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
125 .stop_threshold = INT_MAX,
126 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
127};
128
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129static int af_period_multiplier = 4;
130struct pcm_config pcm_config_rt = {
131 .channels = 2,
132 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
133 .period_size = ULL_PERIOD_SIZE, //1 ms
134 .period_count = 512, //=> buffer size is 512ms
135 .format = PCM_FORMAT_S16_LE,
136 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
137 .stop_threshold = INT_MAX,
138 .silence_threshold = 0,
139 .silence_size = 0,
140 .avail_min = ULL_PERIOD_SIZE, //1 ms
141};
142
Eric Laurentb23d5282013-05-14 15:27:20 -0700143struct pcm_config pcm_config_hdmi_multi = {
144 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
146 .period_size = HDMI_MULTI_PERIOD_SIZE,
147 .period_count = HDMI_MULTI_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = 0,
150 .stop_threshold = INT_MAX,
151 .avail_min = 0,
152};
153
154struct pcm_config pcm_config_audio_capture = {
155 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700156 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
157 .format = PCM_FORMAT_S16_LE,
158};
159
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700160struct pcm_config pcm_config_audio_capture_rt = {
161 .channels = 2,
162 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
163 .period_size = ULL_PERIOD_SIZE,
164 .period_count = 512,
165 .format = PCM_FORMAT_S16_LE,
166 .start_threshold = 0,
167 .stop_threshold = INT_MAX,
168 .silence_threshold = 0,
169 .silence_size = 0,
170 .avail_min = ULL_PERIOD_SIZE, //1 ms
171};
172
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700173#define AFE_PROXY_CHANNEL_COUNT 2
174#define AFE_PROXY_SAMPLING_RATE 48000
175
176#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
177#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
178
179struct pcm_config pcm_config_afe_proxy_playback = {
180 .channels = AFE_PROXY_CHANNEL_COUNT,
181 .rate = AFE_PROXY_SAMPLING_RATE,
182 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
183 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
186 .stop_threshold = INT_MAX,
187 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
188};
189
190#define AFE_PROXY_RECORD_PERIOD_SIZE 768
191#define AFE_PROXY_RECORD_PERIOD_COUNT 4
192
193struct pcm_config pcm_config_afe_proxy_record = {
194 .channels = AFE_PROXY_CHANNEL_COUNT,
195 .rate = AFE_PROXY_SAMPLING_RATE,
196 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
197 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
200 .stop_threshold = INT_MAX,
201 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
202};
203
Ashish Jainf1eaa582016-05-23 20:54:24 +0530204#define AUDIO_MAX_PCM_FORMATS 7
205
206const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
207 [AUDIO_FORMAT_DEFAULT] = 0,
208 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
209 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
210 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
211 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
212 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
213 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
214};
215
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800216const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700217 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
218 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700219 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
220 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700221 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700222 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
227 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
228 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
229 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
230 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700231
Eric Laurentb23d5282013-05-14 15:27:20 -0700232 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700233 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530234 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
235 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
236 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700237 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700238 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700239 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800240 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800241 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700242 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700243
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700244 [USECASE_VOICE2_CALL] = "voice2-call",
245 [USECASE_VOLTE_CALL] = "volte-call",
246 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800247 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800248 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
249 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800250 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700251 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
252 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
253 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800254 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
255 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
256 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
257
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700258 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
259 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700260 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
261 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700262
263 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
264 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700265 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700266};
267
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700268static const audio_usecase_t offload_usecases[] = {
269 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700270 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
274 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
275 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
276 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
277 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700278};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800279
280#define STRING_TO_ENUM(string) { #string, string }
281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800282struct string_to_enum {
283 const char *name;
284 uint32_t value;
285};
286
287static const struct string_to_enum out_channels_name_to_enum_table[] = {
288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700292 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800293 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
294 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
296};
297
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700298static const struct string_to_enum out_formats_name_to_enum_table[] = {
299 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
300 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
301 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700302 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800303 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
304 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
305};
306
307//list of all supported sample rates by HDMI specification.
308static const int out_hdmi_sample_rates[] = {
309 32000, 44100, 48000, 88200, 96000, 176400, 192000,
310};
311
312static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
313 STRING_TO_ENUM(32000),
314 STRING_TO_ENUM(44100),
315 STRING_TO_ENUM(48000),
316 STRING_TO_ENUM(88200),
317 STRING_TO_ENUM(96000),
318 STRING_TO_ENUM(176400),
319 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700320};
321
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700322static struct audio_device *adev = NULL;
323static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700324static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700325//cache last MBDRC cal step level
326static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700327
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700328static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
329 int flags __unused)
330{
331 int dir = 0;
332 switch (uc_id) {
333 case USECASE_AUDIO_RECORD_LOW_LATENCY:
334 dir = 1;
335 case USECASE_AUDIO_PLAYBACK_ULL:
336 break;
337 default:
338 return false;
339 }
340
341 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
342 PCM_PLAYBACK : PCM_CAPTURE);
343 if (adev->adm_is_noirq_avail)
344 return adev->adm_is_noirq_avail(adev->adm_data,
345 adev->snd_card, dev_id, dir);
346 return false;
347}
348
349static void register_out_stream(struct stream_out *out)
350{
351 struct audio_device *adev = out->dev;
352 if (is_offload_usecase(out->usecase) ||
353 !adev->adm_register_output_stream)
354 return;
355
356 // register stream first for backward compatibility
357 adev->adm_register_output_stream(adev->adm_data,
358 out->handle,
359 out->flags);
360
361 if (!adev->adm_set_config)
362 return;
363
364 if (out->realtime)
365 adev->adm_set_config(adev->adm_data,
366 out->handle,
367 out->pcm, &out->config);
368}
369
370static void register_in_stream(struct stream_in *in)
371{
372 struct audio_device *adev = in->dev;
373 if (!adev->adm_register_input_stream)
374 return;
375
376 adev->adm_register_input_stream(adev->adm_data,
377 in->capture_handle,
378 in->flags);
379
380 if (!adev->adm_set_config)
381 return;
382
383 if (in->realtime)
384 adev->adm_set_config(adev->adm_data,
385 in->capture_handle,
386 in->pcm,
387 &in->config);
388}
389
390static void request_out_focus(struct stream_out *out, long ns)
391{
392 struct audio_device *adev = out->dev;
393
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700394 if (adev->adm_request_focus_v2)
395 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
396 else if (adev->adm_request_focus)
397 adev->adm_request_focus(adev->adm_data, out->handle);
398}
399
400static void request_in_focus(struct stream_in *in, long ns)
401{
402 struct audio_device *adev = in->dev;
403
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700404 if (adev->adm_request_focus_v2)
405 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
406 else if (adev->adm_request_focus)
407 adev->adm_request_focus(adev->adm_data, in->capture_handle);
408}
409
410static void release_out_focus(struct stream_out *out)
411{
412 struct audio_device *adev = out->dev;
413
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, out->handle);
416}
417
418static void release_in_focus(struct stream_in *in)
419{
420 struct audio_device *adev = in->dev;
421 if (adev->adm_abandon_focus)
422 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
423}
424
vivek mehtaa76401a2015-04-24 14:12:15 -0700425__attribute__ ((visibility ("default")))
426bool audio_hw_send_gain_dep_calibration(int level) {
427 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700428 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700429
430 pthread_mutex_lock(&adev_init_lock);
431
432 if (adev != NULL && adev->platform != NULL) {
433 pthread_mutex_lock(&adev->lock);
434 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700435
436 // if cal set fails, cache level info
437 // if cal set succeds, reset known last cal set
438 if (!ret_val)
439 last_known_cal_step = level;
440 else if (last_known_cal_step != -1)
441 last_known_cal_step = -1;
442
vivek mehtaa76401a2015-04-24 14:12:15 -0700443 pthread_mutex_unlock(&adev->lock);
444 } else {
445 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
446 }
447
448 pthread_mutex_unlock(&adev_init_lock);
449
450 return ret_val;
451}
452
Ashish Jain5106d362016-05-11 19:23:33 +0530453static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
454{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800455 bool gapless_enabled = false;
456 const char *mixer_ctl_name = "Compress Gapless Playback";
457 struct mixer_ctl *ctl;
458
459 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530460 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
461
462 /*Disable gapless if its AV playback*/
463 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800464
465 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
466 if (!ctl) {
467 ALOGE("%s: Could not get ctl for mixer cmd - %s",
468 __func__, mixer_ctl_name);
469 return -EINVAL;
470 }
471
472 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
473 ALOGE("%s: Could not set gapless mode %d",
474 __func__, gapless_enabled);
475 return -EINVAL;
476 }
477 return 0;
478}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700479
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700480__attribute__ ((visibility ("default")))
481int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
482 int table_size) {
483 int ret_val = 0;
484 ALOGV("%s: enter ... ", __func__);
485
486 pthread_mutex_lock(&adev_init_lock);
487 if (adev == NULL) {
488 ALOGW("%s: adev is NULL .... ", __func__);
489 goto done;
490 }
491
492 pthread_mutex_lock(&adev->lock);
493 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
494 pthread_mutex_unlock(&adev->lock);
495done:
496 pthread_mutex_unlock(&adev_init_lock);
497 ALOGV("%s: exit ... ", __func__);
498 return ret_val;
499}
500
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700501static bool is_supported_format(audio_format_t format)
502{
Eric Laurent86e17132013-09-12 17:49:30 -0700503 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530504 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530505 format == AUDIO_FORMAT_AAC_LC ||
506 format == AUDIO_FORMAT_AAC_HE_V1 ||
507 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530508 format == AUDIO_FORMAT_AAC_ADTS_LC ||
509 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
510 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530511 format == AUDIO_FORMAT_AAC_LATM_LC ||
512 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
513 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530514 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
515 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530516 format == AUDIO_FORMAT_PCM_FLOAT ||
517 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700518 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530519 format == AUDIO_FORMAT_AC3 ||
520 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700521 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530522 format == AUDIO_FORMAT_DTS ||
523 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800524 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530525 format == AUDIO_FORMAT_ALAC ||
526 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530527 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800529 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530530 format == AUDIO_FORMAT_WMA_PRO ||
531 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800532 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700533
534 return false;
535}
536
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700537static inline bool is_mmap_usecase(audio_usecase_t uc_id)
538{
539 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
540 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
541}
542
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530543int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530544{
545 int snd_scard_state;
546
547 if (!adev)
548 return SND_CARD_STATE_OFFLINE;
549
550 pthread_mutex_lock(&adev->snd_card_status.lock);
551 snd_scard_state = adev->snd_card_status.state;
552 pthread_mutex_unlock(&adev->snd_card_status.lock);
553
554 return snd_scard_state;
555}
556
557static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
558{
559 if (!adev)
560 return -ENOSYS;
561
562 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700563 if (adev->snd_card_status.state != snd_scard_state) {
564 adev->snd_card_status.state = snd_scard_state;
565 platform_snd_card_update(adev->platform, snd_scard_state);
566 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530567 pthread_mutex_unlock(&adev->snd_card_status.lock);
568
569 return 0;
570}
571
Avinash Vaish71a8b972014-07-24 15:36:33 +0530572static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
573 struct audio_usecase *uc_info)
574{
575 struct listnode *node;
576 struct audio_usecase *usecase;
577
578 if (uc_info == NULL)
579 return -EINVAL;
580
581 /* Re-route all voice usecases on the shared backend other than the
582 specified usecase to new snd devices */
583 list_for_each(node, &adev->usecase_list) {
584 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800585 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530586 enable_audio_route(adev, usecase);
587 }
588 return 0;
589}
590
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530591static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530592{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530593 ALOGV("%s", __func__);
594 audio_route_apply_and_update_path(adev->audio_route,
595 "asrc-mode");
596 adev->asrc_mode_enabled = true;
597}
598
599static void disable_asrc_mode(struct audio_device *adev)
600{
601 ALOGV("%s", __func__);
602 audio_route_reset_and_update_path(adev->audio_route,
603 "asrc-mode");
604 adev->asrc_mode_enabled = false;
605}
606
607/*
608 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
609 * 44.1 or Native DSD backends are enabled for any of current use case.
610 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
611 * - Disable current mix path use case(Headphone backend) and re-enable it with
612 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
613 * e.g. Naitve DSD or Headphone 44.1 -> + 48
614 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530615static void check_and_set_asrc_mode(struct audio_device *adev,
616 struct audio_usecase *uc_info,
617 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530618{
619 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530620 int i, num_new_devices = 0;
621 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
622 /*
623 *Split snd device for new combo use case
624 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
625 */
626 if (platform_split_snd_device(adev->platform,
627 snd_device,
628 &num_new_devices,
629 split_new_snd_devices) == 0) {
630 for (i = 0; i < num_new_devices; i++)
631 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
632 } else {
633 int new_backend_idx = platform_get_backend_index(snd_device);
634 if (((new_backend_idx == HEADPHONE_BACKEND) ||
635 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
636 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
637 !adev->asrc_mode_enabled) {
638 struct listnode *node = NULL;
639 struct audio_usecase *uc = NULL;
640 struct stream_out *curr_out = NULL;
641 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
642 int i, num_devices, ret = 0;
643 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530644
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530645 list_for_each(node, &adev->usecase_list) {
646 uc = node_to_item(node, struct audio_usecase, list);
647 curr_out = (struct stream_out*) uc->stream.out;
648 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
649 /*
650 *Split snd device for existing combo use case
651 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
652 */
653 ret = platform_split_snd_device(adev->platform,
654 uc->out_snd_device,
655 &num_devices,
656 split_snd_devices);
657 if (ret < 0 || num_devices == 0) {
658 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
659 split_snd_devices[0] = uc->out_snd_device;
660 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800661 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530662 for (i = 0; i < num_devices; i++) {
663 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
664 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
665 if((new_backend_idx == HEADPHONE_BACKEND) &&
666 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
667 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
668 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
669 __func__);
670 enable_asrc_mode(adev);
671 break;
672 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
673 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
674 (usecase_backend_idx == HEADPHONE_BACKEND)) {
675 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
676 __func__);
677 disable_audio_route(adev, uc);
678 disable_snd_device(adev, uc->out_snd_device);
679 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
680 if (new_backend_idx == DSD_NATIVE_BACKEND)
681 audio_route_apply_and_update_path(adev->audio_route,
682 "hph-true-highquality-mode");
683 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
684 (curr_out->bit_width >= 24))
685 audio_route_apply_and_update_path(adev->audio_route,
686 "hph-highquality-mode");
687 enable_asrc_mode(adev);
688 enable_snd_device(adev, uc->out_snd_device);
689 enable_audio_route(adev, uc);
690 break;
691 }
692 }
693 // reset split devices count
694 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800695 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530696 if (adev->asrc_mode_enabled)
697 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530698 }
699 }
700 }
701}
702
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700703int pcm_ioctl(struct pcm *pcm, int request, ...)
704{
705 va_list ap;
706 void * arg;
707 int pcm_fd = *(int*)pcm;
708
709 va_start(ap, request);
710 arg = va_arg(ap, void *);
711 va_end(ap);
712
713 return ioctl(pcm_fd, request, arg);
714}
715
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700716int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700717 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800718{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700720 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530721 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800722
723 if (usecase == NULL)
724 return -EINVAL;
725
726 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
727
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800728 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800730 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700731 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800732
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800733#ifdef DS1_DOLBY_DAP_ENABLED
734 audio_extn_dolby_set_dmid(adev);
735 audio_extn_dolby_set_endpoint(adev);
736#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700737 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700738 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530739 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700740 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530741 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530742 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
743 out = usecase->stream.out;
744 if (out && out->compr)
745 audio_extn_utils_compress_set_clk_rec_mode(usecase);
746 }
747
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752 ALOGV("%s: exit", __func__);
753 return 0;
754}
755
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700756int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700757 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800758{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700760 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800761
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530762 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800763 return -EINVAL;
764
765 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700766 if (usecase->type == PCM_CAPTURE)
767 snd_device = usecase->in_snd_device;
768 else
769 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800770 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700771 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700772 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700773 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700774 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530775 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 ALOGV("%s: exit", __func__);
777 return 0;
778}
779
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700780int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700781 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530783 int i, num_devices = 0;
784 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700785 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
786
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800787 if (snd_device < SND_DEVICE_MIN ||
788 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800789 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800790 return -EINVAL;
791 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792
793 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700794
795 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
796 ALOGE("%s: Invalid sound device returned", __func__);
797 return -EINVAL;
798 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700800 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700801 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802 return 0;
803 }
804
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530805
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700806 if (audio_extn_spkr_prot_is_enabled())
807 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700808
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800809 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
810 audio_extn_spkr_prot_is_enabled()) {
811 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700812 adev->snd_dev_ref_cnt[snd_device]--;
813 return -EINVAL;
814 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200815 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800816 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800817 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200818 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800819 return -EINVAL;
820 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700821 } else if (platform_split_snd_device(adev->platform,
822 snd_device,
823 &num_devices,
824 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530825 for (i = 0; i < num_devices; i++) {
826 enable_snd_device(adev, new_snd_devices[i]);
827 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800828 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700829 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530830
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530831
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530832 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
833 (audio_extn_a2dp_start_playback() < 0)) {
834 ALOGE(" fail to configure A2dp control path ");
835 return -EINVAL;
836 }
837
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700838 /* due to the possibility of calibration overwrite between listen
839 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700840 audio_extn_sound_trigger_update_device_status(snd_device,
841 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530842 audio_extn_listen_update_device_status(snd_device,
843 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700844 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700845 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700846 audio_extn_sound_trigger_update_device_status(snd_device,
847 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530848 audio_extn_listen_update_device_status(snd_device,
849 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700850 return -EINVAL;
851 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300852 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700853 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530854
855 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
856 !adev->native_playback_enabled &&
857 audio_is_true_native_stream_active(adev)) {
858 ALOGD("%s: %d: napb: enabling native mode in hardware",
859 __func__, __LINE__);
860 audio_route_apply_and_update_path(adev->audio_route,
861 "true-native-mode");
862 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800865 return 0;
866}
867
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700868int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700869 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800870{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530871 int i, num_devices = 0;
872 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700873 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
874
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800875 if (snd_device < SND_DEVICE_MIN ||
876 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800877 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800878 return -EINVAL;
879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
881 ALOGE("%s: device ref cnt is already 0", __func__);
882 return -EINVAL;
883 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700884
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700886
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700887 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
888 ALOGE("%s: Invalid sound device returned", __func__);
889 return -EINVAL;
890 }
891
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700893 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530894
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800895 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
896 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700897 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700898 } else if (platform_split_snd_device(adev->platform,
899 snd_device,
900 &num_devices,
901 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530902 for (i = 0; i < num_devices; i++) {
903 disable_snd_device(adev, new_snd_devices[i]);
904 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300905 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700906 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300907 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700908
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530909 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
910 audio_extn_a2dp_stop_playback();
911
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700912 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530913 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530914 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
915 adev->native_playback_enabled) {
916 ALOGD("%s: %d: napb: disabling native mode in hardware",
917 __func__, __LINE__);
918 audio_route_reset_and_update_path(adev->audio_route,
919 "true-native-mode");
920 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530921 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
922 adev->asrc_mode_enabled) {
923 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530924 disable_asrc_mode(adev);
925 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530926 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530927
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200928 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700929 audio_extn_sound_trigger_update_device_status(snd_device,
930 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530931 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800932 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935 return 0;
936}
937
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700938/*
939 legend:
940 uc - existing usecase
941 new_uc - new usecase
942 d1, d11, d2 - SND_DEVICE enums
943 a1, a2 - corresponding ANDROID device enums
944 B1, B2 - backend strings
945
946case 1
947 uc->dev d1 (a1) B1
948 new_uc->dev d1 (a1), d2 (a2) B1, B2
949
950 resolution: disable and enable uc->dev on d1
951
952case 2
953 uc->dev d1 (a1) B1
954 new_uc->dev d11 (a1) B1
955
956 resolution: need to switch uc since d1 and d11 are related
957 (e.g. speaker and voice-speaker)
958 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
959
960case 3
961 uc->dev d1 (a1) B1
962 new_uc->dev d2 (a2) B2
963
964 resolution: no need to switch uc
965
966case 4
967 uc->dev d1 (a1) B1
968 new_uc->dev d2 (a2) B1
969
970 resolution: disable enable uc-dev on d2 since backends match
971 we cannot enable two streams on two different devices if they
972 share the same backend. e.g. if offload is on speaker device using
973 QUAD_MI2S backend and a low-latency stream is started on voice-handset
974 using the same backend, offload must also be switched to voice-handset.
975
976case 5
977 uc->dev d1 (a1) B1
978 new_uc->dev d1 (a1), d2 (a2) B1
979
980 resolution: disable enable uc-dev on d2 since backends match
981 we cannot enable two streams on two different devices if they
982 share the same backend.
983
984case 6
985 uc->dev d1 (a1) B1
986 new_uc->dev d2 (a1) B2
987
988 resolution: no need to switch
989
990case 7
991 uc->dev d1 (a1), d2 (a2) B1, B2
992 new_uc->dev d1 (a1) B1
993
994 resolution: no need to switch
995
996*/
997static snd_device_t derive_playback_snd_device(void * platform,
998 struct audio_usecase *uc,
999 struct audio_usecase *new_uc,
1000 snd_device_t new_snd_device)
1001{
1002 audio_devices_t a1 = uc->stream.out->devices;
1003 audio_devices_t a2 = new_uc->stream.out->devices;
1004
1005 snd_device_t d1 = uc->out_snd_device;
1006 snd_device_t d2 = new_snd_device;
1007
1008 // Treat as a special case when a1 and a2 are not disjoint
1009 if ((a1 != a2) && (a1 & a2)) {
1010 snd_device_t d3[2];
1011 int num_devices = 0;
1012 int ret = platform_split_snd_device(platform,
1013 popcount(a1) > 1 ? d1 : d2,
1014 &num_devices,
1015 d3);
1016 if (ret < 0) {
1017 if (ret != -ENOSYS) {
1018 ALOGW("%s failed to split snd_device %d",
1019 __func__,
1020 popcount(a1) > 1 ? d1 : d2);
1021 }
1022 goto end;
1023 }
1024
1025 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1026 // But if it does happen, we need to give priority to d2 if
1027 // the combo devices active on the existing usecase share a backend.
1028 // This is because we cannot have a usecase active on a combo device
1029 // and a new usecase requests one device in this combo pair.
1030 if (platform_check_backends_match(d3[0], d3[1])) {
1031 return d2; // case 5
1032 } else {
1033 return d1; // case 1
1034 }
1035 } else {
1036 if (platform_check_backends_match(d1, d2)) {
1037 return d2; // case 2, 4
1038 } else {
1039 return d1; // case 6, 3
1040 }
1041 }
1042
1043end:
1044 return d2; // return whatever was calculated before.
1045}
1046
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301048 struct audio_usecase *uc_info,
1049 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050{
1051 struct listnode *node;
1052 struct audio_usecase *usecase;
1053 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301054 snd_device_t uc_derive_snd_device;
1055 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001057 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301058 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 /*
1060 * This function is to make sure that all the usecases that are active on
1061 * the hardware codec backend are always routed to any one device that is
1062 * handled by the hardware codec.
1063 * For example, if low-latency and deep-buffer usecases are currently active
1064 * on speaker and out_set_parameters(headset) is received on low-latency
1065 * output, then we have to make sure deep-buffer is also switched to headset,
1066 * because of the limitation that both the devices cannot be enabled
1067 * at the same time as they share the same backend.
1068 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001069 /*
1070 * This call is to check if we need to force routing for a particular stream
1071 * If there is a backend configuration change for the device when a
1072 * new stream starts, then ADM needs to be closed and re-opened with the new
1073 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001074 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001075 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001076 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1077 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301078 /* For a2dp device reconfigure all active sessions
1079 * with new AFE encoder format based on a2dp state
1080 */
1081 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1082 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1083 audio_extn_a2dp_is_force_device_switch()) {
1084 force_routing = true;
1085 force_restart_session = true;
1086 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301087 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1088
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001089 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001090 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001091 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1093 switch_device[i] = false;
1094
1095 list_for_each(node, &adev->usecase_list) {
1096 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001097
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301098 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1099 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301100 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301101 platform_get_snd_device_name(usecase->out_snd_device),
1102 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301103 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1104 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1105 usecase, uc_info, snd_device);
1106 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1107 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1108 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1109 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1110 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1111 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1112 ((force_restart_session) ||
1113 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301114 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1115 __func__, use_case_table[usecase->id],
1116 platform_get_snd_device_name(usecase->out_snd_device));
1117 disable_audio_route(adev, usecase);
1118 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301119 /* Enable existing usecase on derived playback device */
1120 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301121 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301122 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 }
1124 }
1125
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301126 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1127 num_uc_to_switch);
1128
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001129 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001130 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301132 /* Make sure the previous devices to be disabled first and then enable the
1133 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 list_for_each(node, &adev->usecase_list) {
1135 usecase = node_to_item(node, struct audio_usecase, list);
1136 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001137 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 }
1139 }
1140
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001141 list_for_each(node, &adev->usecase_list) {
1142 usecase = node_to_item(node, struct audio_usecase, list);
1143 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301144 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001145 }
1146 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148 /* Re-route all the usecases on the shared backend other than the
1149 specified usecase to new snd devices */
1150 list_for_each(node, &adev->usecase_list) {
1151 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301152 /* Update the out_snd_device only before enabling the audio route */
1153 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301154 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301155 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301156 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301157 use_case_table[usecase->id],
1158 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001159 /* Update voc calibration before enabling VoIP route */
1160 if (usecase->type == VOIP_CALL)
1161 status = platform_switch_voice_call_device_post(adev->platform,
1162 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001163 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301164 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301165 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 }
1167 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 }
1169}
1170
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301171static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001172 struct audio_usecase *uc_info,
1173 snd_device_t snd_device)
1174{
1175 struct listnode *node;
1176 struct audio_usecase *usecase;
1177 bool switch_device[AUDIO_USECASE_MAX];
1178 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301179 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001180 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301182 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1183 snd_device);
1184 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301185
1186 /*
1187 * Make sure out devices is checked against out codec backend device and
1188 * also in devices against in codec backend. Checking out device against in
1189 * codec backend or vice versa causes issues.
1190 */
1191 if (uc_info->type == PCM_CAPTURE)
1192 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001193 /*
1194 * This function is to make sure that all the active capture usecases
1195 * are always routed to the same input sound device.
1196 * For example, if audio-record and voice-call usecases are currently
1197 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1198 * is received for voice call then we have to make sure that audio-record
1199 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1200 * because of the limitation that two devices cannot be enabled
1201 * at the same time if they share the same backend.
1202 */
1203 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1204 switch_device[i] = false;
1205
1206 list_for_each(node, &adev->usecase_list) {
1207 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301208 /*
1209 * TODO: Enhance below condition to handle BT sco/USB multi recording
1210 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001211 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301213 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301214 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301215 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301216 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001217 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001218 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1219 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001220 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001221 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001222 switch_device[usecase->id] = true;
1223 num_uc_to_switch++;
1224 }
1225 }
1226
1227 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001228 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001229
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301230 /* Make sure the previous devices to be disabled first and then enable the
1231 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001235 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001236 }
1237 }
1238
1239 list_for_each(node, &adev->usecase_list) {
1240 usecase = node_to_item(node, struct audio_usecase, list);
1241 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001242 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001243 }
1244 }
1245
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001246 /* Re-route all the usecases on the shared backend other than the
1247 specified usecase to new snd devices */
1248 list_for_each(node, &adev->usecase_list) {
1249 usecase = node_to_item(node, struct audio_usecase, list);
1250 /* Update the in_snd_device only before enabling the audio route */
1251 if (switch_device[usecase->id] ) {
1252 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001253 if (usecase->type != VOICE_CALL) {
1254 /* Update voc calibration before enabling VoIP route */
1255 if (usecase->type == VOIP_CALL)
1256 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001257 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001258 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301259 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001260 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001261 }
1262 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001263 }
1264}
1265
Mingming Yin3a941d42016-02-17 18:08:05 -08001266static void reset_hdmi_sink_caps(struct stream_out *out) {
1267 int i = 0;
1268
1269 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1270 out->supported_channel_masks[i] = 0;
1271 }
1272 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1273 out->supported_formats[i] = 0;
1274 }
1275 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1276 out->supported_sample_rates[i] = 0;
1277 }
1278}
1279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001281static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282{
Mingming Yin3a941d42016-02-17 18:08:05 -08001283 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001284 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285
Mingming Yin3a941d42016-02-17 18:08:05 -08001286 reset_hdmi_sink_caps(out);
1287
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001288 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001289 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001290 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001291 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001292 }
1293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001296 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001297 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001298 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1299 case 6:
1300 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1301 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1302 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1303 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1304 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1305 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001306 break;
1307 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001308 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001309 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 break;
1311 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001312
1313 // check channel format caps
1314 i = 0;
1315 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1316 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1317 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1318 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1319 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1320 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1321 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1322 }
1323
Ben Romberger1aaaf862017-04-06 17:49:46 -07001324 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1325 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1326 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1327 }
1328
Mingming Yin3a941d42016-02-17 18:08:05 -08001329 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1330 ALOGV(":%s HDMI supports DTS format", __func__);
1331 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1332 }
1333
1334 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1335 ALOGV(":%s HDMI supports DTS HD format", __func__);
1336 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1337 }
1338
1339
1340 // check sample rate caps
1341 i = 0;
1342 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1343 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1344 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1345 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1346 }
1347 }
1348
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001349 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350}
1351
Alexy Josephb1379942016-01-29 15:49:38 -08001352audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001353 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001354{
1355 struct audio_usecase *usecase;
1356 struct listnode *node;
1357
1358 list_for_each(node, &adev->usecase_list) {
1359 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001360 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001361 ALOGV("%s: usecase id %d", __func__, usecase->id);
1362 return usecase->id;
1363 }
1364 }
1365 return USECASE_INVALID;
1366}
1367
Alexy Josephb1379942016-01-29 15:49:38 -08001368struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001369 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001370{
1371 struct audio_usecase *usecase;
1372 struct listnode *node;
1373
1374 list_for_each(node, &adev->usecase_list) {
1375 usecase = node_to_item(node, struct audio_usecase, list);
1376 if (usecase->id == uc_id)
1377 return usecase;
1378 }
1379 return NULL;
1380}
1381
Dhananjay Kumard4833242016-10-06 22:09:12 +05301382struct stream_in *get_next_active_input(const struct audio_device *adev)
1383{
1384 struct audio_usecase *usecase;
1385 struct listnode *node;
1386
1387 list_for_each_reverse(node, &adev->usecase_list) {
1388 usecase = node_to_item(node, struct audio_usecase, list);
1389 if (usecase->type == PCM_CAPTURE)
1390 return usecase->stream.in;
1391 }
1392 return NULL;
1393}
1394
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301395/*
1396 * is a true native playback active
1397 */
1398bool audio_is_true_native_stream_active(struct audio_device *adev)
1399{
1400 bool active = false;
1401 int i = 0;
1402 struct listnode *node;
1403
1404 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1405 ALOGV("%s:napb: not in true mode or non hdphones device",
1406 __func__);
1407 active = false;
1408 goto exit;
1409 }
1410
1411 list_for_each(node, &adev->usecase_list) {
1412 struct audio_usecase *uc;
1413 uc = node_to_item(node, struct audio_usecase, list);
1414 struct stream_out *curr_out =
1415 (struct stream_out*) uc->stream.out;
1416
1417 if (curr_out && PCM_PLAYBACK == uc->type) {
1418 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1419 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1420 uc->id, curr_out->sample_rate,
1421 curr_out->bit_width,
1422 platform_get_snd_device_name(uc->out_snd_device));
1423
1424 if (is_offload_usecase(uc->id) &&
1425 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1426 active = true;
1427 ALOGD("%s:napb:native stream detected", __func__);
1428 }
1429 }
1430 }
1431exit:
1432 return active;
1433}
1434
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301435/*
1436 * if native DSD playback active
1437 */
1438bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1439{
1440 bool active = false;
1441 struct listnode *node = NULL;
1442 struct audio_usecase *uc = NULL;
1443 struct stream_out *curr_out = NULL;
1444
1445 list_for_each(node, &adev->usecase_list) {
1446 uc = node_to_item(node, struct audio_usecase, list);
1447 curr_out = (struct stream_out*) uc->stream.out;
1448
1449 if (curr_out && PCM_PLAYBACK == uc->type &&
1450 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1451 active = true;
1452 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301453 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301454 }
1455 }
1456 return active;
1457}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301458
1459static bool force_device_switch(struct audio_usecase *usecase)
1460{
1461 bool ret = false;
1462 bool is_it_true_mode = false;
1463
1464 if (is_offload_usecase(usecase->id) &&
1465 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001466 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1467 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1468 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301469 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1470 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1471 (!is_it_true_mode && adev->native_playback_enabled)){
1472 ret = true;
1473 ALOGD("napb: time to toggle native mode");
1474 }
1475 }
1476
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301477 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301478 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1479 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301480 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001481 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301482 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301483 ALOGD("Force a2dp device switch to update new encoder config");
1484 ret = true;
1485 }
1486
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301487 return ret;
1488}
1489
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001490int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001492 snd_device_t out_snd_device = SND_DEVICE_NONE;
1493 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 struct audio_usecase *usecase = NULL;
1495 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001496 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001497 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001498 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301501 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1502
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 usecase = get_usecase_from_list(adev, uc_id);
1504 if (usecase == NULL) {
1505 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1506 return -EINVAL;
1507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001509 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001510 (usecase->type == VOIP_CALL) ||
1511 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301512 if(usecase->stream.out == NULL) {
1513 ALOGE("%s: stream.out is NULL", __func__);
1514 return -EINVAL;
1515 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001516 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001517 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001518 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 usecase->devices = usecase->stream.out->devices;
1520 } else {
1521 /*
1522 * If the voice call is active, use the sound devices of voice call usecase
1523 * so that it would not result any device switch. All the usecases will
1524 * be switched to new device when select_devices() is called for voice call
1525 * usecase. This is to avoid switching devices for voice call when
1526 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001527 * choose voice call device only if the use case device is
1528 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001530 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001531 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001532 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001533 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1534 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301535 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1536 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001537 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 in_snd_device = vc_usecase->in_snd_device;
1539 out_snd_device = vc_usecase->out_snd_device;
1540 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001541 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001542 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001543 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001544 if ((voip_usecase != NULL) &&
1545 (usecase->type == PCM_PLAYBACK) &&
1546 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001547 out_snd_device_backend_match = platform_check_backends_match(
1548 voip_usecase->out_snd_device,
1549 platform_get_output_snd_device(
1550 adev->platform,
1551 usecase->stream.out));
1552 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001553 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001554 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1555 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001556 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001557 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001558 in_snd_device = voip_usecase->in_snd_device;
1559 out_snd_device = voip_usecase->out_snd_device;
1560 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001561 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001562 hfp_ucid = audio_extn_hfp_get_usecase();
1563 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001564 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001565 in_snd_device = hfp_usecase->in_snd_device;
1566 out_snd_device = hfp_usecase->out_snd_device;
1567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 }
1569 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301570 if (usecase->stream.out == NULL) {
1571 ALOGE("%s: stream.out is NULL", __func__);
1572 return -EINVAL;
1573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574 usecase->devices = usecase->stream.out->devices;
1575 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001576 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001577 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001578 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001579 if (usecase->stream.out == adev->primary_output &&
1580 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001581 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001582 select_devices(adev, adev->active_input->usecase);
1583 }
1584 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301586 if (usecase->stream.in == NULL) {
1587 ALOGE("%s: stream.in is NULL", __func__);
1588 return -EINVAL;
1589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 usecase->devices = usecase->stream.in->device;
1591 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001592 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001593 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001594 if (adev->active_input &&
1595 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301596 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1597 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1598 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001599 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001600 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001601 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1602 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001603 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001604 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001605 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001606 }
1607 }
1608
1609 if (out_snd_device == usecase->out_snd_device &&
1610 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301611
1612 if (!force_device_switch(usecase))
1613 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614 }
1615
sangwoobc677242013-08-08 16:53:43 +09001616 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001617 out_snd_device, platform_get_snd_device_name(out_snd_device),
1618 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 /*
1621 * Limitation: While in call, to do a device switch we need to disable
1622 * and enable both RX and TX devices though one of them is same as current
1623 * device.
1624 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001625 if ((usecase->type == VOICE_CALL) &&
1626 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1627 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001628 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001629 }
1630
1631 if (((usecase->type == VOICE_CALL) ||
1632 (usecase->type == VOIP_CALL)) &&
1633 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1634 /* Disable sidetone only if voice/voip call already exists */
1635 if (voice_is_call_state_active(adev) ||
1636 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001637 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001638
1639 /* Disable aanc only if voice call exists */
1640 if (voice_is_call_state_active(adev))
1641 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001642 }
1643
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001644 /* Disable current sound devices */
1645 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001646 disable_audio_route(adev, usecase);
1647 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648 }
1649
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001650 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001651 disable_audio_route(adev, usecase);
1652 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 }
1654
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001655 /* Applicable only on the targets that has external modem.
1656 * New device information should be sent to modem before enabling
1657 * the devices to reduce in-call device switch time.
1658 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001659 if ((usecase->type == VOICE_CALL) &&
1660 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1661 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001662 status = platform_switch_voice_call_enable_device_config(adev->platform,
1663 out_snd_device,
1664 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001665 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001666
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667 /* Enable new sound devices */
1668 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001669 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301670 if (platform_check_codec_asrc_support(adev->platform))
1671 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001672 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 }
1674
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001675 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301676 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001677 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679
Avinash Vaish71a8b972014-07-24 15:36:33 +05301680 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001681 status = platform_switch_voice_call_device_post(adev->platform,
1682 out_snd_device,
1683 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301684 enable_audio_route_for_voice_usecases(adev, usecase);
1685 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001686
sangwoo170731f2013-06-08 15:36:36 +09001687 usecase->in_snd_device = in_snd_device;
1688 usecase->out_snd_device = out_snd_device;
1689
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301690 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1691 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301692 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001693 if ((24 == usecase->stream.out->bit_width) &&
1694 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1695 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1696 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1697 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1698 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1699 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1700 /*
1701 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1702 * configured device sample rate, if not update the COPP rate to be equal to the
1703 * device sample rate, else open COPP at stream sample rate
1704 */
1705 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1706 usecase->stream.out->sample_rate,
1707 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301708 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1709 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001710 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1711 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1712 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1713 }
1714
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001715 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001716 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001717 audio_extn_gef_notify_device_config(
1718 usecase->stream.out->devices,
1719 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001720 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001721 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001722 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301723 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001724 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001725
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001726 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001727 /* Enable aanc only if voice call exists */
1728 if (voice_is_call_state_active(adev))
1729 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1730
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001731 /* Enable sidetone only if other voice/voip call already exists */
1732 if (voice_is_call_state_active(adev) ||
1733 voice_extn_compress_voip_is_started(adev))
1734 voice_set_sidetone(adev, out_snd_device, true);
1735 }
1736
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001737 /* Applicable only on the targets that has external modem.
1738 * Enable device command should be sent to modem only after
1739 * enabling voice call mixer controls
1740 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001741 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001742 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1743 out_snd_device,
1744 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301745 ALOGD("%s: done",__func__);
1746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 return status;
1748}
1749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750static int stop_input_stream(struct stream_in *in)
1751{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301752 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 struct audio_usecase *uc_info;
1754 struct audio_device *adev = in->dev;
1755
Eric Laurent994a6932013-07-17 11:51:42 -07001756 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001757 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 uc_info = get_usecase_from_list(adev, in->usecase);
1759 if (uc_info == NULL) {
1760 ALOGE("%s: Could not find the usecase (%d) in the list",
1761 __func__, in->usecase);
1762 return -EINVAL;
1763 }
1764
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001765 /* Close in-call recording streams */
1766 voice_check_and_stop_incall_rec_usecase(adev, in);
1767
Eric Laurent150dbfe2013-02-27 14:31:02 -08001768 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001769 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770
1771 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001772 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001774 list_remove(&uc_info->list);
1775 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001777 adev->active_input = get_next_active_input(adev);
1778
Eric Laurent994a6932013-07-17 11:51:42 -07001779 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 return ret;
1781}
1782
1783int start_input_stream(struct stream_in *in)
1784{
1785 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001786 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 struct audio_usecase *uc_info;
1788 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301789 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Mingming Yin2664a5b2015-09-03 10:53:11 -07001791 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1792 if (get_usecase_from_list(adev, usecase) == NULL)
1793 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301794 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1795 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001796
Naresh Tanniru80659832014-06-04 18:17:56 +05301797
1798 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301799 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301800 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301801 goto error_config;
1802 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301803
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001804 /* Check if source matches incall recording usecase criteria */
1805 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1806 if (ret)
1807 goto error_config;
1808 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001809 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1810
1811 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1812 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1813 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001814 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001815 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001816
Eric Laurentb23d5282013-05-14 15:27:20 -07001817 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 if (in->pcm_device_id < 0) {
1819 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1820 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001821 ret = -EINVAL;
1822 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824
1825 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001827
1828 if (!uc_info) {
1829 ret = -ENOMEM;
1830 goto error_config;
1831 }
1832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 uc_info->id = in->usecase;
1834 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001835 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 uc_info->devices = in->device;
1837 uc_info->in_snd_device = SND_DEVICE_NONE;
1838 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001840 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301841 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1842 adev->perf_lock_opts,
1843 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001844 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301846 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1847 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001848
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301849 if (audio_extn_cin_attached_usecase(in->usecase)) {
1850 ret = audio_extn_cin_start_input_stream(in);
1851 if (ret)
1852 goto error_open;
1853 else
1854 goto done_open;
1855 }
1856
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001857 unsigned int flags = PCM_IN;
1858 unsigned int pcm_open_retry_count = 0;
1859
1860 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1861 flags |= PCM_MMAP | PCM_NOIRQ;
1862 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001863 } else if (in->realtime) {
1864 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001865 }
1866
1867 while (1) {
1868 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1869 flags, &in->config);
1870 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1871 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1872 if (in->pcm != NULL) {
1873 pcm_close(in->pcm);
1874 in->pcm = NULL;
1875 }
1876 if (pcm_open_retry_count-- == 0) {
1877 ret = -EIO;
1878 goto error_open;
1879 }
1880 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1881 continue;
1882 }
1883 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001885
1886 ALOGV("%s: pcm_prepare", __func__);
1887 ret = pcm_prepare(in->pcm);
1888 if (ret < 0) {
1889 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1890 pcm_close(in->pcm);
1891 in->pcm = NULL;
1892 goto error_open;
1893 }
1894
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001895 register_in_stream(in);
1896 if (in->realtime) {
1897 ret = pcm_start(in->pcm);
1898 if (ret < 0)
1899 goto error_open;
1900 }
1901
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301902done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301903 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001904 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001905
Eric Laurentc8400632013-02-14 19:04:54 -08001906 return ret;
1907
1908error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301909 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001911error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301912 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301913 /*
1914 * sleep 50ms to allow sufficient time for kernel
1915 * drivers to recover incases like SSR.
1916 */
1917 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001919
1920 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921}
1922
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001923void lock_input_stream(struct stream_in *in)
1924{
1925 pthread_mutex_lock(&in->pre_lock);
1926 pthread_mutex_lock(&in->lock);
1927 pthread_mutex_unlock(&in->pre_lock);
1928}
1929
1930void lock_output_stream(struct stream_out *out)
1931{
1932 pthread_mutex_lock(&out->pre_lock);
1933 pthread_mutex_lock(&out->lock);
1934 pthread_mutex_unlock(&out->pre_lock);
1935}
1936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001937/* must be called with out->lock locked */
1938static int send_offload_cmd_l(struct stream_out* out, int command)
1939{
1940 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1941
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001942 if (!cmd) {
1943 ALOGE("failed to allocate mem for command 0x%x", command);
1944 return -ENOMEM;
1945 }
1946
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001947 ALOGVV("%s %d", __func__, command);
1948
1949 cmd->cmd = command;
1950 list_add_tail(&out->offload_cmd_list, &cmd->node);
1951 pthread_cond_signal(&out->offload_cond);
1952 return 0;
1953}
1954
1955/* must be called iwth out->lock locked */
1956static void stop_compressed_output_l(struct stream_out *out)
1957{
1958 out->offload_state = OFFLOAD_STATE_IDLE;
1959 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001960 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001961 if (out->compr != NULL) {
1962 compress_stop(out->compr);
1963 while (out->offload_thread_blocked) {
1964 pthread_cond_wait(&out->cond, &out->lock);
1965 }
1966 }
1967}
1968
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001969bool is_offload_usecase(audio_usecase_t uc_id)
1970{
1971 unsigned int i;
1972 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1973 if (uc_id == offload_usecases[i])
1974 return true;
1975 }
1976 return false;
1977}
1978
Dhananjay Kumarac341582017-02-23 23:42:25 +05301979static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001980{
vivek mehta446c3962015-09-14 10:57:35 -07001981 audio_usecase_t ret_uc = USECASE_INVALID;
1982 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001983 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001984 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301985 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001986 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1987 else
1988 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001989
vivek mehta446c3962015-09-14 10:57:35 -07001990 pthread_mutex_lock(&adev->lock);
1991 if (get_usecase_from_list(adev, ret_uc) != NULL)
1992 ret_uc = USECASE_INVALID;
1993 pthread_mutex_unlock(&adev->lock);
1994
1995 return ret_uc;
1996 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001997
1998 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001999 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2000 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2001 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2002 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002003 break;
2004 }
2005 }
vivek mehta446c3962015-09-14 10:57:35 -07002006
2007 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2008 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002009}
2010
2011static void free_offload_usecase(struct audio_device *adev,
2012 audio_usecase_t uc_id)
2013{
vivek mehta446c3962015-09-14 10:57:35 -07002014 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002015 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002016
2017 if (!adev->multi_offload_enable)
2018 return;
2019
2020 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2021 if (offload_usecases[offload_uc_index] == uc_id) {
2022 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002023 break;
2024 }
2025 }
2026 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2027}
2028
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029static void *offload_thread_loop(void *context)
2030{
2031 struct stream_out *out = (struct stream_out *) context;
2032 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002033 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002034
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2036 set_sched_policy(0, SP_FOREGROUND);
2037 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2038
2039 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002040 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002041 for (;;) {
2042 struct offload_cmd *cmd = NULL;
2043 stream_callback_event_t event;
2044 bool send_callback = false;
2045
2046 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2047 __func__, list_empty(&out->offload_cmd_list),
2048 out->offload_state);
2049 if (list_empty(&out->offload_cmd_list)) {
2050 ALOGV("%s SLEEPING", __func__);
2051 pthread_cond_wait(&out->offload_cond, &out->lock);
2052 ALOGV("%s RUNNING", __func__);
2053 continue;
2054 }
2055
2056 item = list_head(&out->offload_cmd_list);
2057 cmd = node_to_item(item, struct offload_cmd, node);
2058 list_remove(item);
2059
2060 ALOGVV("%s STATE %d CMD %d out->compr %p",
2061 __func__, out->offload_state, cmd->cmd, out->compr);
2062
2063 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2064 free(cmd);
2065 break;
2066 }
2067
2068 if (out->compr == NULL) {
2069 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002070 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002071 pthread_cond_signal(&out->cond);
2072 continue;
2073 }
2074 out->offload_thread_blocked = true;
2075 pthread_mutex_unlock(&out->lock);
2076 send_callback = false;
2077 switch(cmd->cmd) {
2078 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002079 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002080 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002081 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 send_callback = true;
2083 event = STREAM_CBK_EVENT_WRITE_READY;
2084 break;
2085 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002086 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302087 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002088 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302089 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002090 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302091 if (ret < 0)
2092 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302093 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302094 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002095 compress_drain(out->compr);
2096 else
2097 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302098 if (ret != -ENETRESET) {
2099 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302100 pthread_mutex_lock(&out->lock);
2101 out->send_new_metadata = 1;
2102 out->send_next_track_params = true;
2103 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302104 event = STREAM_CBK_EVENT_DRAIN_READY;
2105 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2106 } else
2107 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 break;
2109 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002110 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002112 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113 send_callback = true;
2114 event = STREAM_CBK_EVENT_DRAIN_READY;
2115 break;
2116 default:
2117 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2118 break;
2119 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002120 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121 out->offload_thread_blocked = false;
2122 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002123 if (send_callback && out->client_callback) {
2124 ALOGVV("%s: sending client_callback event %d", __func__, event);
2125 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002126 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 free(cmd);
2128 }
2129
2130 pthread_cond_signal(&out->cond);
2131 while (!list_empty(&out->offload_cmd_list)) {
2132 item = list_head(&out->offload_cmd_list);
2133 list_remove(item);
2134 free(node_to_item(item, struct offload_cmd, node));
2135 }
2136 pthread_mutex_unlock(&out->lock);
2137
2138 return NULL;
2139}
2140
2141static int create_offload_callback_thread(struct stream_out *out)
2142{
2143 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2144 list_init(&out->offload_cmd_list);
2145 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2146 offload_thread_loop, out);
2147 return 0;
2148}
2149
2150static int destroy_offload_callback_thread(struct stream_out *out)
2151{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002152 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 stop_compressed_output_l(out);
2154 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2155
2156 pthread_mutex_unlock(&out->lock);
2157 pthread_join(out->offload_thread, (void **) NULL);
2158 pthread_cond_destroy(&out->offload_cond);
2159
2160 return 0;
2161}
2162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163static int stop_output_stream(struct stream_out *out)
2164{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302165 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 struct audio_usecase *uc_info;
2167 struct audio_device *adev = out->dev;
2168
Eric Laurent994a6932013-07-17 11:51:42 -07002169 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002170 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 uc_info = get_usecase_from_list(adev, out->usecase);
2172 if (uc_info == NULL) {
2173 ALOGE("%s: Could not find the usecase (%d) in the list",
2174 __func__, out->usecase);
2175 return -EINVAL;
2176 }
2177
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002178 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302179 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002180 if (adev->visualizer_stop_output != NULL)
2181 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002182
2183 audio_extn_dts_remove_state_notifier_node(out->usecase);
2184
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002185 if (adev->offload_effects_stop_output != NULL)
2186 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2187 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002188
Eric Laurent150dbfe2013-02-27 14:31:02 -08002189 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002190 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002191
2192 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002193 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002195 list_remove(&uc_info->list);
2196 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002198 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302199 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002200 ALOGV("Disable passthrough , reset mixer to pcm");
2201 /* NO_PASSTHROUGH */
2202 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002203 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002204 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2205 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002206
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302207 /* Must be called after removing the usecase from list */
2208 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302209 audio_extn_keep_alive_start();
2210
Manish Dewangan14956cc2017-02-14 18:54:42 +05302211 /*reset delay_param to 0*/
2212 out->delay_param.start_delay = 0;
2213
Eric Laurent994a6932013-07-17 11:51:42 -07002214 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 return ret;
2216}
2217
2218int start_output_stream(struct stream_out *out)
2219{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 struct audio_usecase *uc_info;
2222 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302223 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002224 char mixer_ctl_name[128];
2225 struct mixer_ctl *ctl = NULL;
2226 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002228 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2229 ret = -EINVAL;
2230 goto error_config;
2231 }
2232
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302233 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2234 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2235 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302236
Naresh Tanniru80659832014-06-04 18:17:56 +05302237 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302238 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302239 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302240 goto error_config;
2241 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302242
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302243 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2244 if (!audio_extn_a2dp_is_ready()) {
2245 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2246 //combo usecase just by pass a2dp
2247 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2248 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2249 } else {
2250 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2251 ret = -EAGAIN;
2252 goto error_config;
2253 }
2254 }
2255 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002256 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257 if (out->pcm_device_id < 0) {
2258 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2259 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002260 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002261 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262 }
2263
2264 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002265
2266 if (!uc_info) {
2267 ret = -ENOMEM;
2268 goto error_config;
2269 }
2270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271 uc_info->id = out->usecase;
2272 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002273 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002274 uc_info->devices = out->devices;
2275 uc_info->in_snd_device = SND_DEVICE_NONE;
2276 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002277 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302279 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2280 adev->perf_lock_opts,
2281 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302282
2283 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2284 audio_extn_keep_alive_stop();
2285 if (audio_extn_passthru_is_enabled() &&
2286 audio_extn_passthru_is_passthrough_stream(out)) {
2287 audio_extn_passthru_on_start(out);
2288 audio_extn_passthru_update_stream_configuration(adev, out);
2289 }
2290 }
2291
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002292 select_devices(adev, out->usecase);
2293
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002294 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2295 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002296 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002297 unsigned int flags = PCM_OUT;
2298 unsigned int pcm_open_retry_count = 0;
2299 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2300 flags |= PCM_MMAP | PCM_NOIRQ;
2301 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002302 } else if (out->realtime) {
2303 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002304 } else
2305 flags |= PCM_MONOTONIC;
2306
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002307 if ((adev->vr_audio_mode_enabled) &&
2308 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2309 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2310 "PCM_Dev %d Topology", out->pcm_device_id);
2311 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2312 if (!ctl) {
2313 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2314 __func__, mixer_ctl_name);
2315 } else {
2316 //if success use ULLPP
2317 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2318 __func__, mixer_ctl_name, out->pcm_device_id);
2319 //There is a still a possibility that some sessions
2320 // that request for FAST|RAW when 3D audio is active
2321 //can go through ULLPP. Ideally we expects apps to
2322 //listen to audio focus and stop concurrent playback
2323 //Also, we will look for mode flag (voice_in_communication)
2324 //before enabling the realtime flag.
2325 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2326 }
2327 }
2328
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002329 while (1) {
2330 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2331 flags, &out->config);
2332 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2333 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2334 if (out->pcm != NULL) {
2335 pcm_close(out->pcm);
2336 out->pcm = NULL;
2337 }
2338 if (pcm_open_retry_count-- == 0) {
2339 ret = -EIO;
2340 goto error_open;
2341 }
2342 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2343 continue;
2344 }
2345 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002347
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002348 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2349 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002350
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002351 ALOGV("%s: pcm_prepare", __func__);
2352 if (pcm_is_ready(out->pcm)) {
2353 ret = pcm_prepare(out->pcm);
2354 if (ret < 0) {
2355 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2356 pcm_close(out->pcm);
2357 out->pcm = NULL;
2358 goto error_open;
2359 }
2360 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302361 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2362 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002364 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2365 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002367 out->compr = compress_open(adev->snd_card,
2368 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 COMPRESS_IN, &out->compr_config);
2370 if (out->compr && !is_compress_ready(out->compr)) {
2371 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2372 compress_close(out->compr);
2373 out->compr = NULL;
2374 ret = -EIO;
2375 goto error_open;
2376 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302377 /* compress_open sends params of the track, so reset the flag here */
2378 out->is_compr_metadata_avail = false;
2379
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002380 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002381 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002382
Fred Oh3f43e742015-03-04 18:42:34 -08002383 /* Since small bufs uses blocking writes, a write will be blocked
2384 for the default max poll time (20s) in the event of an SSR.
2385 Reduce the poll time to observe and deal with SSR faster.
2386 */
Ashish Jain5106d362016-05-11 19:23:33 +05302387 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002388 compress_set_max_poll_wait(out->compr, 1000);
2389 }
2390
Manish Dewangan69426c82017-01-30 17:35:36 +05302391 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302392 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan27346042017-03-01 12:56:12 +05302393 /* set render window if it was set before compress_open() */
2394 if (out->render_window.render_ws != 0 && out->render_window.render_we != 0)
2395 audio_extn_utils_compress_set_render_window(out,
2396 &out->render_window);
Manish Dewangan14956cc2017-02-14 18:54:42 +05302397 audio_extn_utils_compress_set_start_delay(out, &out->delay_param);
Manish Dewangan69426c82017-01-30 17:35:36 +05302398
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002399 audio_extn_dts_create_state_notifier_node(out->usecase);
2400 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2401 popcount(out->channel_mask),
2402 out->playback_started);
2403
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002404#ifdef DS1_DOLBY_DDP_ENABLED
2405 if (audio_extn_is_dolby_format(out->format))
2406 audio_extn_dolby_send_ddp_endp_params(adev);
2407#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302408 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2409 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002410 if (adev->visualizer_start_output != NULL)
2411 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2412 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302413 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002414 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002415 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002417
2418 if (ret == 0) {
2419 register_out_stream(out);
2420 if (out->realtime) {
2421 ret = pcm_start(out->pcm);
2422 if (ret < 0)
2423 goto error_open;
2424 }
2425 }
2426
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302427 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002428 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002429
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002430 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002431error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302432 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002434error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302435 /*
2436 * sleep 50ms to allow sufficient time for kernel
2437 * drivers to recover incases like SSR.
2438 */
2439 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002440 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441}
2442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443static int check_input_parameters(uint32_t sample_rate,
2444 audio_format_t format,
2445 int channel_count)
2446{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002447 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302449 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2450 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2451 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002452 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302453 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002454
2455 switch (channel_count) {
2456 case 1:
2457 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302458 case 3:
2459 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002460 case 6:
2461 break;
2462 default:
2463 ret = -EINVAL;
2464 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465
2466 switch (sample_rate) {
2467 case 8000:
2468 case 11025:
2469 case 12000:
2470 case 16000:
2471 case 22050:
2472 case 24000:
2473 case 32000:
2474 case 44100:
2475 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302476 case 96000:
2477 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 break;
2479 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002480 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 }
2482
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002483 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484}
2485
2486static size_t get_input_buffer_size(uint32_t sample_rate,
2487 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002488 int channel_count,
2489 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490{
2491 size_t size = 0;
2492
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002493 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2494 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002496 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002497 if (is_low_latency)
2498 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302499
2500 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002502 /* make sure the size is multiple of 32 bytes
2503 * At 48 kHz mono 16-bit PCM:
2504 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2505 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2506 */
2507 size += 0x1f;
2508 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002509
2510 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511}
2512
Ashish Jain058165c2016-09-28 23:18:48 +05302513static size_t get_output_period_size(uint32_t sample_rate,
2514 audio_format_t format,
2515 int channel_count,
2516 int duration /*in millisecs*/)
2517{
2518 size_t size = 0;
2519 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2520
2521 if ((duration == 0) || (sample_rate == 0) ||
2522 (bytes_per_sample == 0) || (channel_count == 0)) {
2523 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2524 bytes_per_sample, channel_count);
2525 return -EINVAL;
2526 }
2527
2528 size = (sample_rate *
2529 duration *
2530 bytes_per_sample *
2531 channel_count) / 1000;
2532 /*
2533 * To have same PCM samples for all channels, the buffer size requires to
2534 * be multiple of (number of channels * bytes per sample)
2535 * For writes to succeed, the buffer must be written at address which is multiple of 32
2536 */
2537 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2538
2539 return (size/(channel_count * bytes_per_sample));
2540}
2541
Ashish Jain5106d362016-05-11 19:23:33 +05302542static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2543{
2544 uint64_t actual_frames_rendered = 0;
2545 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2546
2547 /* This adjustment accounts for buffering after app processor.
2548 * It is based on estimated DSP latency per use case, rather than exact.
2549 */
2550 int64_t platform_latency = platform_render_latency(out->usecase) *
2551 out->sample_rate / 1000000LL;
2552
2553 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2554 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2555 * hence only estimate.
2556 */
2557 int64_t signed_frames = out->written - kernel_buffer_size;
2558
2559 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2560
2561 if (signed_frames > 0)
2562 actual_frames_rendered = signed_frames;
2563
2564 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2565 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2566 (long long int)out->written, (int)kernel_buffer_size,
2567 audio_bytes_per_sample(out->compr_config.codec->format),
2568 popcount(out->channel_mask));
2569
2570 return actual_frames_rendered;
2571}
2572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2574{
2575 struct stream_out *out = (struct stream_out *)stream;
2576
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002577 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578}
2579
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002580static int out_set_sample_rate(struct audio_stream *stream __unused,
2581 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582{
2583 return -ENOSYS;
2584}
2585
2586static size_t out_get_buffer_size(const struct audio_stream *stream)
2587{
2588 struct stream_out *out = (struct stream_out *)stream;
2589
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302590 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2591 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2592 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2593 else
2594 return out->compr_config.fragment_size;
2595 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002596 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302597 else if (is_offload_usecase(out->usecase) &&
2598 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302599 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002600
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002601 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002602 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603}
2604
2605static uint32_t out_get_channels(const struct audio_stream *stream)
2606{
2607 struct stream_out *out = (struct stream_out *)stream;
2608
2609 return out->channel_mask;
2610}
2611
2612static audio_format_t out_get_format(const struct audio_stream *stream)
2613{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002614 struct stream_out *out = (struct stream_out *)stream;
2615
2616 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617}
2618
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002619static int out_set_format(struct audio_stream *stream __unused,
2620 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621{
2622 return -ENOSYS;
2623}
2624
2625static int out_standby(struct audio_stream *stream)
2626{
2627 struct stream_out *out = (struct stream_out *)stream;
2628 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002629
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302630 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2631 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002633 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002635 if (adev->adm_deregister_stream)
2636 adev->adm_deregister_stream(adev->adm_data, out->handle);
2637
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002638 if (is_offload_usecase(out->usecase))
2639 stop_compressed_output_l(out);
2640
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002641 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002643 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2644 voice_extn_compress_voip_close_output_stream(stream);
2645 pthread_mutex_unlock(&adev->lock);
2646 pthread_mutex_unlock(&out->lock);
2647 ALOGD("VOIP output entered standby");
2648 return 0;
2649 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002650 if (out->pcm) {
2651 pcm_close(out->pcm);
2652 out->pcm = NULL;
2653 }
2654 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002655 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302656 out->send_next_track_params = false;
2657 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002658 out->gapless_mdata.encoder_delay = 0;
2659 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 if (out->compr != NULL) {
2661 compress_close(out->compr);
2662 out->compr = NULL;
2663 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002664 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002666 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 }
2668 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302669 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 return 0;
2671}
2672
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002673static int out_dump(const struct audio_stream *stream __unused,
2674 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675{
2676 return 0;
2677}
2678
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002679static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2680{
2681 int ret = 0;
2682 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002683
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002684 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002685 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002686 return -EINVAL;
2687 }
2688
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302689 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002690
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002691 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2692 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302693 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002694 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002695 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2696 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302697 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002698 }
2699
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002700 ALOGV("%s new encoder delay %u and padding %u", __func__,
2701 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2702
2703 return 0;
2704}
2705
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002706static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2707{
2708 return out == adev->primary_output || out == adev->voice_tx_output;
2709}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2712{
2713 struct stream_out *out = (struct stream_out *)stream;
2714 struct audio_device *adev = out->dev;
2715 struct str_parms *parms;
2716 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002717 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718
sangwoobc677242013-08-08 16:53:43 +09002719 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002720 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302722 if (!parms)
2723 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002724 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2725 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002727 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002728 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002730 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002731 * When HDMI cable is unplugged the music playback is paused and
2732 * the policy manager sends routing=0. But the audioflinger continues
2733 * to write data until standby time (3sec). As the HDMI core is
2734 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002735 * Avoid this by routing audio to speaker until standby.
2736 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002737 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2738 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302739 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002740 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2741 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002742 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302743 /*
2744 * When A2DP is disconnected the
2745 * music playback is paused and the policy manager sends routing=0
2746 * But the audioflingercontinues to write data until standby time
2747 * (3sec). As BT is turned off, the write gets blocked.
2748 * Avoid this by routing audio to speaker until standby.
2749 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002750 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302751 (val == AUDIO_DEVICE_NONE)) {
2752 val = AUDIO_DEVICE_OUT_SPEAKER;
2753 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302754 /* To avoid a2dp to sco overlapping / BT device improper state
2755 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302756 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302757 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2758 if (!audio_extn_a2dp_is_ready()) {
2759 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2760 //combo usecase just by pass a2dp
2761 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2762 val = AUDIO_DEVICE_OUT_SPEAKER;
2763 } else {
2764 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2765 /* update device to a2dp and don't route as BT returned error
2766 * However it is still possible a2dp routing called because
2767 * of current active device disconnection (like wired headset)
2768 */
2769 out->devices = val;
2770 pthread_mutex_unlock(&out->lock);
2771 pthread_mutex_unlock(&adev->lock);
2772 goto error;
2773 }
2774 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302775 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002776 /*
2777 * select_devices() call below switches all the usecases on the same
2778 * backend to the new device. Refer to check_usecases_codec_backend() in
2779 * the select_devices(). But how do we undo this?
2780 *
2781 * For example, music playback is active on headset (deep-buffer usecase)
2782 * and if we go to ringtones and select a ringtone, low-latency usecase
2783 * will be started on headset+speaker. As we can't enable headset+speaker
2784 * and headset devices at the same time, select_devices() switches the music
2785 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2786 * So when the ringtone playback is completed, how do we undo the same?
2787 *
2788 * We are relying on the out_set_parameters() call on deep-buffer output,
2789 * once the ringtone playback is ended.
2790 * NOTE: We should not check if the current devices are same as new devices.
2791 * Because select_devices() must be called to switch back the music
2792 * playback to headset.
2793 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002794 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002795 audio_devices_t new_dev = val;
2796 bool same_dev = out->devices == new_dev;
2797 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002798
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002799 if (output_drives_call(adev, out)) {
2800 if(!voice_is_in_call(adev)) {
2801 if (adev->mode == AUDIO_MODE_IN_CALL) {
2802 adev->current_call_output = out;
2803 ret = voice_start_call(adev);
2804 }
2805 } else {
2806 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002807 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002808 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002809 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002810
2811 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002812 if (!same_dev) {
2813 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302814 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2815 adev->perf_lock_opts,
2816 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002817 if (adev->adm_on_routing_change)
2818 adev->adm_on_routing_change(adev->adm_data,
2819 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002820 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002821 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302822 if (!same_dev)
2823 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002824 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002825 }
2826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002828 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002830
2831 if (out == adev->primary_output) {
2832 pthread_mutex_lock(&adev->lock);
2833 audio_extn_set_parameters(adev, parms);
2834 pthread_mutex_unlock(&adev->lock);
2835 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002836 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002837 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002838 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002839
2840 audio_extn_dts_create_state_notifier_node(out->usecase);
2841 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2842 popcount(out->channel_mask),
2843 out->playback_started);
2844
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002845 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002846 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002847
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302848 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2849 if (err >= 0) {
2850 strlcpy(out->profile, value, sizeof(out->profile));
2851 ALOGV("updating stream profile with value '%s'", out->profile);
2852 lock_output_stream(out);
2853 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2854 &adev->streams_output_cfg_list,
2855 out->devices, out->flags, out->format,
2856 out->sample_rate, out->bit_width,
2857 out->channel_mask, out->profile,
2858 &out->app_type_cfg);
2859 pthread_mutex_unlock(&out->lock);
2860 }
2861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302863error:
Eric Laurent994a6932013-07-17 11:51:42 -07002864 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 return ret;
2866}
2867
2868static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2869{
2870 struct stream_out *out = (struct stream_out *)stream;
2871 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002872 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002873 char value[256];
2874 struct str_parms *reply = str_parms_create();
2875 size_t i, j;
2876 int ret;
2877 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002878
2879 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002880 if (reply) {
2881 str_parms_destroy(reply);
2882 }
2883 if (query) {
2884 str_parms_destroy(query);
2885 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002886 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2887 return NULL;
2888 }
2889
Eric Laurent994a6932013-07-17 11:51:42 -07002890 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2892 if (ret >= 0) {
2893 value[0] = '\0';
2894 i = 0;
2895 while (out->supported_channel_masks[i] != 0) {
2896 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2897 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2898 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002899 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002901 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 first = false;
2903 break;
2904 }
2905 }
2906 i++;
2907 }
2908 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2909 str = str_parms_to_str(reply);
2910 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002911 voice_extn_out_get_parameters(out, query, reply);
2912 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002913 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002914 free(str);
2915 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002916 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002918
Alexy Joseph62142aa2015-11-16 15:10:34 -08002919
2920 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2921 if (ret >= 0) {
2922 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302923 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2924 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002925 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302926 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002927 } else {
2928 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302929 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002930 }
2931 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002932 if (str)
2933 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002934 str = str_parms_to_str(reply);
2935 }
2936
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002937 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2938 if (ret >= 0) {
2939 value[0] = '\0';
2940 i = 0;
2941 first = true;
2942 while (out->supported_formats[i] != 0) {
2943 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2944 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2945 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002946 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002947 }
2948 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2949 first = false;
2950 break;
2951 }
2952 }
2953 i++;
2954 }
2955 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002956 if (str)
2957 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002958 str = str_parms_to_str(reply);
2959 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002960
2961 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2962 if (ret >= 0) {
2963 value[0] = '\0';
2964 i = 0;
2965 first = true;
2966 while (out->supported_sample_rates[i] != 0) {
2967 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2968 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2969 if (!first) {
2970 strlcat(value, "|", sizeof(value));
2971 }
2972 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2973 first = false;
2974 break;
2975 }
2976 }
2977 i++;
2978 }
2979 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2980 if (str)
2981 free(str);
2982 str = str_parms_to_str(reply);
2983 }
2984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 str_parms_destroy(query);
2986 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002987 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 return str;
2989}
2990
2991static uint32_t out_get_latency(const struct audio_stream_out *stream)
2992{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002993 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002995 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996
Alexy Josephaa54c872014-12-03 02:46:47 -08002997 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302998 lock_output_stream(out);
2999 latency = audio_extn_utils_compress_get_dsp_latency(out);
3000 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003001 } else if (out->realtime) {
3002 // since the buffer won't be filled up faster than realtime,
3003 // return a smaller number
3004 if (out->config.rate)
3005 period_ms = (out->af_period_multiplier * out->config.period_size *
3006 1000) / (out->config.rate);
3007 else
3008 period_ms = 0;
3009 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003010 } else {
3011 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003012 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003013 }
3014
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003015 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3016 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3017 latency += audio_extn_a2dp_get_encoder_latency();
3018
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303019 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003020 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021}
3022
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303023static float AmpToDb(float amplification)
3024{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303025 float db = DSD_VOLUME_MIN_DB;
3026 if (amplification > 0) {
3027 db = 20 * log10(amplification);
3028 if(db < DSD_VOLUME_MIN_DB)
3029 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303030 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303031 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303032}
3033
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034static int out_set_volume(struct audio_stream_out *stream, float left,
3035 float right)
3036{
Eric Laurenta9024de2013-04-04 09:19:12 -07003037 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003038 int volume[2];
3039
Eric Laurenta9024de2013-04-04 09:19:12 -07003040 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3041 /* only take left channel into account: the API is for stereo anyway */
3042 out->muted = (left == 0.0f);
3043 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003044 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303045 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003046 /*
3047 * Set mute or umute on HDMI passthrough stream.
3048 * Only take left channel into account.
3049 * Mute is 0 and unmute 1
3050 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303051 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303052 } else if (out->format == AUDIO_FORMAT_DSD){
3053 char mixer_ctl_name[128] = "DSD Volume";
3054 struct audio_device *adev = out->dev;
3055 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3056
3057 if (!ctl) {
3058 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3059 __func__, mixer_ctl_name);
3060 return -EINVAL;
3061 }
3062 volume[0] = (int)(AmpToDb(left));
3063 volume[1] = (int)(AmpToDb(right));
3064 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3065 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003066 } else {
3067 char mixer_ctl_name[128];
3068 struct audio_device *adev = out->dev;
3069 struct mixer_ctl *ctl;
3070 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003071 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003073 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3074 "Compress Playback %d Volume", pcm_device_id);
3075 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3076 if (!ctl) {
3077 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3078 __func__, mixer_ctl_name);
3079 return -EINVAL;
3080 }
3081 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3082 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3083 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3084 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003086 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 return -ENOSYS;
3089}
3090
3091static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3092 size_t bytes)
3093{
3094 struct stream_out *out = (struct stream_out *)stream;
3095 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303096 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003097 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003099 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303100
Naresh Tanniru80659832014-06-04 18:17:56 +05303101 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003102
Dhananjay Kumarac341582017-02-23 23:42:25 +05303103 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303104 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303105 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3106 pthread_mutex_unlock(&out->lock);
3107 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303108 } else {
3109 /* increase written size during SSR to avoid mismatch
3110 * with the written frames count in AF
3111 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003112 // bytes per frame
3113 size_t bpf = audio_bytes_per_sample(out->format) *
3114 audio_channel_count_from_out_mask(out->channel_mask);
3115 if (bpf != 0)
3116 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303117 ALOGD(" %s: sound card is not active/SSR state", __func__);
3118 ret= -EIO;
3119 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303120 }
3121 }
3122
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303123 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303124 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3125 if (audio_bytes_per_sample(out->format) != 0)
3126 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3127 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303128 goto exit;
3129 }
3130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003132 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003133 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003134 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3135 ret = voice_extn_compress_voip_start_output_stream(out);
3136 else
3137 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003138 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003141 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 goto exit;
3143 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003144
3145 if (last_known_cal_step != -1) {
3146 ALOGD("%s: retry previous failed cal level set", __func__);
3147 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3148 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150
Ashish Jain81eb2a82015-05-13 10:52:34 +05303151 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003152 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303153 adev->is_channel_status_set = true;
3154 }
3155
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003156 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003157 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003158 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003159 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003160 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3161 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303162 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3163 ALOGD("copl(%p):send next track params in gapless", out);
3164 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3165 out->send_next_track_params = false;
3166 out->is_compr_metadata_avail = false;
3167 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003168 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303169 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303170 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003171
Ashish Jain83a6cc22016-06-28 14:34:17 +05303172 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303173 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303174 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303175 pthread_mutex_unlock(&out->lock);
3176 return -EINVAL;
3177 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303178 audio_format_t dst_format = out->hal_op_format;
3179 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303180
3181 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3182 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3183
Ashish Jain83a6cc22016-06-28 14:34:17 +05303184 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303185 dst_format,
3186 buffer,
3187 src_format,
3188 frames);
3189
Ashish Jain83a6cc22016-06-28 14:34:17 +05303190 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303191 bytes_to_write);
3192
3193 /*Convert written bytes in audio flinger format*/
3194 if (ret > 0)
3195 ret = ((ret * format_to_bitwidth_table[out->format]) /
3196 format_to_bitwidth_table[dst_format]);
3197 }
3198 } else
3199 ret = compress_write(out->compr, buffer, bytes);
3200
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303201 if (ret < 0)
3202 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303203 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303204 /*msg to cb thread only if non blocking write is enabled*/
3205 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303206 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003207 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303208 } else if (-ENETRESET == ret) {
3209 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3210 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3211 pthread_mutex_unlock(&out->lock);
3212 out_standby(&out->stream.common);
3213 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003214 }
Ashish Jain5106d362016-05-11 19:23:33 +05303215 if ( ret == (ssize_t)bytes && !out->non_blocking)
3216 out->written += bytes;
3217
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303218 /* Call compr start only when non-zero bytes of data is there to be rendered */
3219 if (!out->playback_started && ret > 0) {
3220 int status = compress_start(out->compr);
3221 if (status < 0) {
3222 ret = status;
3223 ALOGE("%s: compr start failed with err %d", __func__, errno);
3224 goto exit;
3225 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003226 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003227 out->playback_started = 1;
3228 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003229
3230 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3231 popcount(out->channel_mask),
3232 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003233 }
3234 pthread_mutex_unlock(&out->lock);
3235 return ret;
3236 } else {
3237 if (out->pcm) {
3238 if (out->muted)
3239 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003240
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303241 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003242
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003243 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003244
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003245 if (out->config.rate)
3246 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3247 out->config.rate;
3248
3249 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3250
3251 request_out_focus(out, ns);
3252
3253 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003254 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003255 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303256 out->convert_buffer != NULL) {
3257
3258 memcpy_by_audio_format(out->convert_buffer,
3259 out->hal_op_format,
3260 buffer,
3261 out->hal_ip_format,
3262 out->config.period_size * out->config.channels);
3263
3264 ret = pcm_write(out->pcm, out->convert_buffer,
3265 (out->config.period_size *
3266 out->config.channels *
3267 format_to_bitwidth_table[out->hal_op_format]));
3268 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003269 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303270 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003271
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003272 release_out_focus(out);
3273
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303274 if (ret < 0)
3275 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303276 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3277 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3278 else
3279 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003280 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281 }
3282
3283exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303284 /* ToDo: There may be a corner case when SSR happens back to back during
3285 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303286 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303287 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303288 }
3289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 pthread_mutex_unlock(&out->lock);
3291
3292 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003293 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003294 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303295 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303296 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303297 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303298 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303299 out->standby = true;
3300 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303302 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3303 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3304 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305 }
3306 return bytes;
3307}
3308
3309static int out_get_render_position(const struct audio_stream_out *stream,
3310 uint32_t *dsp_frames)
3311{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003312 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303313 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003314
3315 if (dsp_frames == NULL)
3316 return -EINVAL;
3317
3318 *dsp_frames = 0;
3319 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003320 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303321
3322 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3323 * this operation and adev_close_output_stream(where out gets reset).
3324 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303325 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303326 *dsp_frames = get_actual_pcm_frames_rendered(out);
3327 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3328 return 0;
3329 }
3330
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003331 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303332 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303333 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303335 if (ret < 0)
3336 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303338 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003339 }
3340 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303341 if (-ENETRESET == ret) {
3342 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3343 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3344 return -EINVAL;
3345 } else if(ret < 0) {
3346 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3347 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303348 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3349 /*
3350 * Handle corner case where compress session is closed during SSR
3351 * and timestamp is queried
3352 */
3353 ALOGE(" ERROR: sound card not active, return error");
3354 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303355 } else {
3356 return 0;
3357 }
Zhou Song32a556e2015-05-05 10:46:56 +08003358 } else if (audio_is_linear_pcm(out->format)) {
3359 *dsp_frames = out->written;
3360 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003361 } else
3362 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363}
3364
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003365static int out_add_audio_effect(const struct audio_stream *stream __unused,
3366 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367{
3368 return 0;
3369}
3370
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003371static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3372 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373{
3374 return 0;
3375}
3376
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003377static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3378 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379{
3380 return -EINVAL;
3381}
3382
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003383static int out_get_presentation_position(const struct audio_stream_out *stream,
3384 uint64_t *frames, struct timespec *timestamp)
3385{
3386 struct stream_out *out = (struct stream_out *)stream;
3387 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003388 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003389
Ashish Jain5106d362016-05-11 19:23:33 +05303390 /* below piece of code is not guarded against any lock because audioFliner serializes
3391 * this operation and adev_close_output_stream( where out gets reset).
3392 */
3393 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303394 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303395 *frames = get_actual_pcm_frames_rendered(out);
3396 /* this is the best we can do */
3397 clock_gettime(CLOCK_MONOTONIC, timestamp);
3398 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3399 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3400 return 0;
3401 }
3402
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003403 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003404
Ashish Jain5106d362016-05-11 19:23:33 +05303405 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3406 ret = compress_get_tstamp(out->compr, &dsp_frames,
3407 &out->sample_rate);
3408 ALOGVV("%s rendered frames %ld sample_rate %d",
3409 __func__, dsp_frames, out->sample_rate);
3410 *frames = dsp_frames;
3411 if (ret < 0)
3412 ret = -errno;
3413 if (-ENETRESET == ret) {
3414 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3415 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3416 ret = -EINVAL;
3417 } else
3418 ret = 0;
3419 /* this is the best we can do */
3420 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003421 } else {
3422 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003423 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003424 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3425 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003426 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003427 // This adjustment accounts for buffering after app processor.
3428 // It is based on estimated DSP latency per use case, rather than exact.
3429 signed_frames -=
3430 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3431
Eric Laurent949a0892013-09-20 09:20:13 -07003432 // It would be unusual for this value to be negative, but check just in case ...
3433 if (signed_frames >= 0) {
3434 *frames = signed_frames;
3435 ret = 0;
3436 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003437 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303438 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3439 *frames = out->written;
3440 clock_gettime(CLOCK_MONOTONIC, timestamp);
3441 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003442 }
3443 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003444 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003445 return ret;
3446}
3447
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448static int out_set_callback(struct audio_stream_out *stream,
3449 stream_callback_t callback, void *cookie)
3450{
3451 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003452 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453
3454 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003455 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003456 out->client_callback = callback;
3457 out->client_cookie = cookie;
3458 if (out->adsp_hdlr_stream_handle) {
3459 ret = audio_extn_adsp_hdlr_stream_set_callback(
3460 out->adsp_hdlr_stream_handle,
3461 callback,
3462 cookie);
3463 if (ret)
3464 ALOGW("%s:adsp hdlr callback registration failed %d",
3465 __func__, ret);
3466 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467 pthread_mutex_unlock(&out->lock);
3468 return 0;
3469}
3470
3471static int out_pause(struct audio_stream_out* stream)
3472{
3473 struct stream_out *out = (struct stream_out *)stream;
3474 int status = -ENOSYS;
3475 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003476 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003477 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003478 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003479 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303480 struct audio_device *adev = out->dev;
3481 int snd_scard_state = get_snd_card_state(adev);
3482
3483 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3484 status = compress_pause(out->compr);
3485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003486 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003487
Mingming Yin21854652016-04-13 11:54:02 -07003488 if (audio_extn_passthru_is_active()) {
3489 ALOGV("offload use case, pause passthru");
3490 audio_extn_passthru_on_pause(out);
3491 }
3492
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303493 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003494 audio_extn_dts_notify_playback_state(out->usecase, 0,
3495 out->sample_rate, popcount(out->channel_mask),
3496 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497 }
3498 pthread_mutex_unlock(&out->lock);
3499 }
3500 return status;
3501}
3502
3503static int out_resume(struct audio_stream_out* stream)
3504{
3505 struct stream_out *out = (struct stream_out *)stream;
3506 int status = -ENOSYS;
3507 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003508 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003509 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003511 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303513 struct audio_device *adev = out->dev;
3514 int snd_scard_state = get_snd_card_state(adev);
3515
Mingming Yin21854652016-04-13 11:54:02 -07003516 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3517 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3518 pthread_mutex_lock(&out->dev->lock);
3519 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003520 pthread_mutex_unlock(&out->dev->lock);
3521 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303522 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003523 }
3524 if (!status) {
3525 out->offload_state = OFFLOAD_STATE_PLAYING;
3526 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303527 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003528 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3529 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003530 }
3531 pthread_mutex_unlock(&out->lock);
3532 }
3533 return status;
3534}
3535
3536static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3537{
3538 struct stream_out *out = (struct stream_out *)stream;
3539 int status = -ENOSYS;
3540 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003541 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003542 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3544 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3545 else
3546 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3547 pthread_mutex_unlock(&out->lock);
3548 }
3549 return status;
3550}
3551
3552static int out_flush(struct audio_stream_out* stream)
3553{
3554 struct stream_out *out = (struct stream_out *)stream;
3555 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003556 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003557 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003558 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003559 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3560 stop_compressed_output_l(out);
3561 out->written = 0;
3562 } else {
3563 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3564 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003565 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003566 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003567 return 0;
3568 }
3569 return -ENOSYS;
3570}
3571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572/** audio_stream_in implementation **/
3573static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3574{
3575 struct stream_in *in = (struct stream_in *)stream;
3576
3577 return in->config.rate;
3578}
3579
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003580static int in_set_sample_rate(struct audio_stream *stream __unused,
3581 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582{
3583 return -ENOSYS;
3584}
3585
3586static size_t in_get_buffer_size(const struct audio_stream *stream)
3587{
3588 struct stream_in *in = (struct stream_in *)stream;
3589
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003590 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3591 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003592 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3593 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303594 else if(audio_extn_cin_attached_usecase(in->usecase))
3595 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003596
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003597 return in->config.period_size * in->af_period_multiplier *
3598 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599}
3600
3601static uint32_t in_get_channels(const struct audio_stream *stream)
3602{
3603 struct stream_in *in = (struct stream_in *)stream;
3604
3605 return in->channel_mask;
3606}
3607
3608static audio_format_t in_get_format(const struct audio_stream *stream)
3609{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003610 struct stream_in *in = (struct stream_in *)stream;
3611
3612 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613}
3614
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003615static int in_set_format(struct audio_stream *stream __unused,
3616 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617{
3618 return -ENOSYS;
3619}
3620
3621static int in_standby(struct audio_stream *stream)
3622{
3623 struct stream_in *in = (struct stream_in *)stream;
3624 struct audio_device *adev = in->dev;
3625 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303626 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3627 stream, in->usecase, use_case_table[in->usecase]);
3628
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003629 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003630 if (!in->standby && in->is_st_session) {
3631 ALOGD("%s: sound trigger pcm stop lab", __func__);
3632 audio_extn_sound_trigger_stop_lab(in);
3633 in->standby = 1;
3634 }
3635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003637 if (adev->adm_deregister_stream)
3638 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3639
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003640 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003642 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3643 voice_extn_compress_voip_close_input_stream(stream);
3644 ALOGD("VOIP input entered standby");
3645 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303646 if (audio_extn_cin_attached_usecase(in->usecase))
3647 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003648 if (in->pcm) {
3649 pcm_close(in->pcm);
3650 in->pcm = NULL;
3651 }
3652 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003653 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003654 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 }
3656 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003657 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 return status;
3659}
3660
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003661static int in_dump(const struct audio_stream *stream __unused,
3662 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663{
3664 return 0;
3665}
3666
3667static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3668{
3669 struct stream_in *in = (struct stream_in *)stream;
3670 struct audio_device *adev = in->dev;
3671 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003673 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303675 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676 parms = str_parms_create_str(kvpairs);
3677
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303678 if (!parms)
3679 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003680 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003681 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003682
3683 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3684 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685 val = atoi(value);
3686 /* no audio source uses val == 0 */
3687 if ((in->source != val) && (val != 0)) {
3688 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003689 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3690 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3691 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003692 (in->config.rate == 8000 || in->config.rate == 16000 ||
3693 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003694 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003695 err = voice_extn_compress_voip_open_input_stream(in);
3696 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003697 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003698 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003699 }
3700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 }
3702 }
3703
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003704 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3705 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003707 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 in->device = val;
3709 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003710 if (!in->standby && !in->is_st_session) {
3711 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003712 if (adev->adm_on_routing_change)
3713 adev->adm_on_routing_change(adev->adm_data,
3714 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003715 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003716 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 }
3718 }
3719
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303720 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3721 if (err >= 0) {
3722 strlcpy(in->profile, value, sizeof(in->profile));
3723 ALOGV("updating stream profile with value '%s'", in->profile);
3724 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3725 &adev->streams_input_cfg_list,
3726 in->device, in->flags, in->format,
3727 in->sample_rate, in->bit_width,
3728 in->profile, &in->app_type_cfg);
3729 }
3730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003732 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733
3734 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303735error:
Eric Laurent994a6932013-07-17 11:51:42 -07003736 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 return ret;
3738}
3739
3740static char* in_get_parameters(const struct audio_stream *stream,
3741 const char *keys)
3742{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003743 struct stream_in *in = (struct stream_in *)stream;
3744 struct str_parms *query = str_parms_create_str(keys);
3745 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003746 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003747
3748 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003749 if (reply) {
3750 str_parms_destroy(reply);
3751 }
3752 if (query) {
3753 str_parms_destroy(query);
3754 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003755 ALOGE("in_get_parameters: failed to create query or reply");
3756 return NULL;
3757 }
3758
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003759 ALOGV("%s: enter: keys - %s", __func__, keys);
3760
3761 voice_extn_in_get_parameters(in, query, reply);
3762
3763 str = str_parms_to_str(reply);
3764 str_parms_destroy(query);
3765 str_parms_destroy(reply);
3766
3767 ALOGV("%s: exit: returns - %s", __func__, str);
3768 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769}
3770
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003771static int in_set_gain(struct audio_stream_in *stream __unused,
3772 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773{
3774 return 0;
3775}
3776
3777static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3778 size_t bytes)
3779{
3780 struct stream_in *in = (struct stream_in *)stream;
3781 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303782 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303783 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303784 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003785
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003786 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303787
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003788 if (in->is_st_session) {
3789 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3790 /* Read from sound trigger HAL */
3791 audio_extn_sound_trigger_read(in, buffer, bytes);
3792 pthread_mutex_unlock(&in->lock);
3793 return bytes;
3794 }
3795
Ashish Jainbbce4322016-02-16 13:25:27 +05303796 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003797 ALOGD(" %s: sound card is not active/SSR state", __func__);
3798 ret= -EIO;;
3799 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303800 }
3801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003803 pthread_mutex_lock(&adev->lock);
3804 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3805 ret = voice_extn_compress_voip_start_input_stream(in);
3806 else
3807 ret = start_input_stream(in);
3808 pthread_mutex_unlock(&adev->lock);
3809 if (ret != 0) {
3810 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 }
3812 in->standby = 0;
3813 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003815 // what's the duration requested by the client?
3816 long ns = 0;
3817
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303818 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003819 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3820 in->config.rate;
3821
3822 request_in_focus(in, ns);
3823 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003824
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303825 if (audio_extn_cin_attached_usecase(in->usecase)) {
3826 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3827 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303828 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003829 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303830 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003831 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003832 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003833 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303834 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003835 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303836 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3837 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3838 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3839 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303840 ret = -EINVAL;
3841 goto exit;
3842 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303843 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303844 ret = -errno;
3845 }
3846 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303847 /* bytes read is always set to bytes for non compress usecases */
3848 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 }
3850
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003851 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853 /*
3854 * Instead of writing zeroes here, we could trust the hardware
3855 * to always provide zeroes when muted.
3856 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303857 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3858 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 memset(buffer, 0, bytes);
3860
3861exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303862 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303863 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003864 if (-ENETRESET == ret)
3865 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 pthread_mutex_unlock(&in->lock);
3868
3869 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303870 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303871 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303872 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303873 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303874 in->standby = true;
3875 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303876 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3877 bytes_read = bytes;
3878 memset(buffer, 0, bytes);
3879 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003881 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303882 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303883 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303885 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886}
3887
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003888static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889{
3890 return 0;
3891}
3892
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003893static int add_remove_audio_effect(const struct audio_stream *stream,
3894 effect_handle_t effect,
3895 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003897 struct stream_in *in = (struct stream_in *)stream;
3898 int status = 0;
3899 effect_descriptor_t desc;
3900
3901 status = (*effect)->get_descriptor(effect, &desc);
3902 if (status != 0)
3903 return status;
3904
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003905 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003906 pthread_mutex_lock(&in->dev->lock);
3907 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3908 in->enable_aec != enable &&
3909 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3910 in->enable_aec = enable;
3911 if (!in->standby)
3912 select_devices(in->dev, in->usecase);
3913 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003914 if (in->enable_ns != enable &&
3915 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3916 in->enable_ns = enable;
3917 if (!in->standby)
3918 select_devices(in->dev, in->usecase);
3919 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003920 pthread_mutex_unlock(&in->dev->lock);
3921 pthread_mutex_unlock(&in->lock);
3922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923 return 0;
3924}
3925
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003926static int in_add_audio_effect(const struct audio_stream *stream,
3927 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928{
Eric Laurent994a6932013-07-17 11:51:42 -07003929 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003930 return add_remove_audio_effect(stream, effect, true);
3931}
3932
3933static int in_remove_audio_effect(const struct audio_stream *stream,
3934 effect_handle_t effect)
3935{
Eric Laurent994a6932013-07-17 11:51:42 -07003936 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003937 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003938}
3939
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303940int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 audio_io_handle_t handle,
3942 audio_devices_t devices,
3943 audio_output_flags_t flags,
3944 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003945 struct audio_stream_out **stream_out,
3946 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947{
3948 struct audio_device *adev = (struct audio_device *)dev;
3949 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303950 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003951 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003952 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303955
3956 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3957 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003958 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303959 return -EINVAL;
3960 }
3961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3963
Mingming Yin3a941d42016-02-17 18:08:05 -08003964 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3965 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303966 devices, flags, &out->stream);
3967
3968
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003969 if (!out) {
3970 return -ENOMEM;
3971 }
3972
Haynes Mathew George204045b2015-02-25 20:32:03 -08003973 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003974 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003975 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977 if (devices == AUDIO_DEVICE_NONE)
3978 devices = AUDIO_DEVICE_OUT_SPEAKER;
3979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003980 out->flags = flags;
3981 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003982 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003983 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984 out->sample_rate = config->sample_rate;
3985 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3986 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003987 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003988 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003989 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303990 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003991
Mingming Yin3a941d42016-02-17 18:08:05 -08003992 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3993 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3994 pthread_mutex_lock(&adev->lock);
3995 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3996 ret = read_hdmi_sink_caps(out);
3997 pthread_mutex_unlock(&adev->lock);
3998 if (ret != 0) {
3999 if (ret == -ENOSYS) {
4000 /* ignore and go with default */
4001 ret = 0;
4002 } else {
4003 ALOGE("error reading hdmi sink caps");
4004 goto error_open;
4005 }
4006 }
4007 }
4008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304010 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004011 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004012 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004013 ret = voice_extn_compress_voip_open_output_stream(out);
4014 if (ret != 0) {
4015 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4016 __func__, ret);
4017 goto error_open;
4018 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004019 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304020 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004021
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004022 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4023 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4024 ALOGE("%s: Unsupported Offload information", __func__);
4025 ret = -EINVAL;
4026 goto error_open;
4027 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004028
Mingming Yin3a941d42016-02-17 18:08:05 -08004029 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004030 if(config->offload_info.format == 0)
4031 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004032 if (config->offload_info.sample_rate == 0)
4033 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004034 }
4035
Mingming Yin90310102013-11-13 16:57:00 -08004036 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304037 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004038 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004039 ret = -EINVAL;
4040 goto error_open;
4041 }
4042
4043 out->compr_config.codec = (struct snd_codec *)
4044 calloc(1, sizeof(struct snd_codec));
4045
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004046 if (!out->compr_config.codec) {
4047 ret = -ENOMEM;
4048 goto error_open;
4049 }
4050
Dhananjay Kumarac341582017-02-23 23:42:25 +05304051 out->stream.pause = out_pause;
4052 out->stream.resume = out_resume;
4053 out->stream.flush = out_flush;
4054 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004055 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004056 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304057 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004058 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304059 } else {
4060 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4061 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004062 }
vivek mehta446c3962015-09-14 10:57:35 -07004063
4064 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004065 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4066 config->format == 0 && config->sample_rate == 0 &&
4067 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004068 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004069 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4070 } else {
4071 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4072 ret = -EEXIST;
4073 goto error_open;
4074 }
vivek mehta446c3962015-09-14 10:57:35 -07004075 }
4076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004077 if (config->offload_info.channel_mask)
4078 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004079 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004080 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004081 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004082 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304083 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004084 ret = -EINVAL;
4085 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004086 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004087
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004088 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004089 out->sample_rate = config->offload_info.sample_rate;
4090
Mingming Yin3ee55c62014-08-04 14:23:35 -07004091 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004092
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304093 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4094 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4095 audio_extn_dolby_send_ddp_endp_params(adev);
4096 audio_extn_dolby_set_dmid(adev);
4097 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004098
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004099 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004100 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004101 out->compr_config.codec->bit_rate =
4102 config->offload_info.bit_rate;
4103 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304104 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004105 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304106 /* Update bit width only for non passthrough usecases.
4107 * For passthrough usecases, the output will always be opened @16 bit
4108 */
4109 if (!audio_extn_passthru_is_passthrough_stream(out))
4110 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304111
4112 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4113 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4114 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4115
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004116 /*TODO: Do we need to change it for passthrough */
4117 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004118
Manish Dewangana6fc5442015-08-24 20:30:31 +05304119 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4120 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304121 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304122 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304123 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4124 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304125
4126 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4127 AUDIO_FORMAT_PCM) {
4128
4129 /*Based on platform support, configure appropriate alsa format for corresponding
4130 *hal input format.
4131 */
4132 out->compr_config.codec->format = hal_format_to_alsa(
4133 config->offload_info.format);
4134
Ashish Jain83a6cc22016-06-28 14:34:17 +05304135 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304136 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304137 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304138
Dhananjay Kumarac341582017-02-23 23:42:25 +05304139 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304140 *hal input format and alsa format might differ based on platform support.
4141 */
4142 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304143 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304144
4145 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4146
4147 /* Check if alsa session is configured with the same format as HAL input format,
4148 * if not then derive correct fragment size needed to accomodate the
4149 * conversion of HAL input format to alsa format.
4150 */
4151 audio_extn_utils_update_direct_pcm_fragment_size(out);
4152
4153 /*if hal input and output fragment size is different this indicates HAL input format is
4154 *not same as the alsa format
4155 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304156 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304157 /*Allocate a buffer to convert input data to the alsa configured format.
4158 *size of convert buffer is equal to the size required to hold one fragment size
4159 *worth of pcm data, this is because flinger does not write more than fragment_size
4160 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304161 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4162 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304163 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4164 ret = -ENOMEM;
4165 goto error_open;
4166 }
4167 }
4168 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4169 out->compr_config.fragment_size =
4170 audio_extn_passthru_get_buffer_size(&config->offload_info);
4171 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4172 } else {
4173 out->compr_config.fragment_size =
4174 platform_get_compress_offload_buffer_size(&config->offload_info);
4175 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4176 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004177
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304178 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4179 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4180 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004181 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304182 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004183
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304184 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4185 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4186 }
4187
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004188 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4189 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004190
Manish Dewangan69426c82017-01-30 17:35:36 +05304191 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4192 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4193 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4194 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4195 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4196 } else {
4197 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4198 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004199
Manish Dewangan27346042017-03-01 12:56:12 +05304200 memset(&out->render_window, 0,
4201 sizeof(struct audio_out_render_window_param));
4202
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004203 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304204 out->send_next_track_params = false;
4205 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004206 out->offload_state = OFFLOAD_STATE_IDLE;
4207 out->playback_started = 0;
4208
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004209 audio_extn_dts_create_state_notifier_node(out->usecase);
4210
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004211 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4212 __func__, config->offload_info.version,
4213 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304214
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304215 /* Check if DSD audio format is supported in codec
4216 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304217 */
4218
4219 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304220 (!platform_check_codec_dsd_support(adev->platform) ||
4221 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304222 ret = -EINVAL;
4223 goto error_open;
4224 }
4225
Ashish Jain5106d362016-05-11 19:23:33 +05304226 /* Disable gapless if any of the following is true
4227 * passthrough playback
4228 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304229 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304230 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304231 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304232 (config->format == AUDIO_FORMAT_DSD) ||
4233 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304234 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304235 check_and_set_gapless_mode(adev, false);
4236 } else
4237 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004238
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304239 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004240 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4241 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304242 if (config->format == AUDIO_FORMAT_DSD) {
4243 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4244 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4245 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004246
4247 create_offload_callback_thread(out);
4248
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004249 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304250 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004251 if (ret != 0) {
4252 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4253 __func__, ret);
4254 goto error_open;
4255 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004256 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4257 if (config->sample_rate == 0)
4258 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4259 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4260 config->sample_rate != 8000) {
4261 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4262 ret = -EINVAL;
4263 goto error_open;
4264 }
4265 out->sample_rate = config->sample_rate;
4266 out->config.rate = config->sample_rate;
4267 if (config->format == AUDIO_FORMAT_DEFAULT)
4268 config->format = AUDIO_FORMAT_PCM_16_BIT;
4269 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4270 config->format = AUDIO_FORMAT_PCM_16_BIT;
4271 ret = -EINVAL;
4272 goto error_open;
4273 }
4274 out->format = config->format;
4275 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4276 out->config = pcm_config_afe_proxy_playback;
4277 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004278 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304279 unsigned int channels = 0;
4280 /*Update config params to default if not set by the caller*/
4281 if (config->sample_rate == 0)
4282 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4283 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4284 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4285 if (config->format == AUDIO_FORMAT_DEFAULT)
4286 config->format = AUDIO_FORMAT_PCM_16_BIT;
4287
4288 channels = audio_channel_count_from_out_mask(out->channel_mask);
4289
Ashish Jain83a6cc22016-06-28 14:34:17 +05304290 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4291 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004292 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4293 out->flags);
4294 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304295 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4296 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4297 out->config = pcm_config_low_latency;
4298 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4299 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4300 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304301 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4302 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4303 if (out->config.period_size <= 0) {
4304 ALOGE("Invalid configuration period size is not valid");
4305 ret = -EINVAL;
4306 goto error_open;
4307 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304308 } else {
4309 /* primary path is the default path selected if no other outputs are available/suitable */
4310 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4311 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4312 }
4313 out->hal_ip_format = format = out->format;
4314 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4315 out->hal_op_format = pcm_format_to_hal(out->config.format);
4316 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4317 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004318 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304319 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304320 if (out->hal_ip_format != out->hal_op_format) {
4321 uint32_t buffer_size = out->config.period_size *
4322 format_to_bitwidth_table[out->hal_op_format] *
4323 out->config.channels;
4324 out->convert_buffer = calloc(1, buffer_size);
4325 if (out->convert_buffer == NULL){
4326 ALOGE("Allocation failed for convert buffer for size %d",
4327 out->compr_config.fragment_size);
4328 ret = -ENOMEM;
4329 goto error_open;
4330 }
4331 ALOGD("Convert buffer allocated of size %d", buffer_size);
4332 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333 }
4334
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004335 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4336 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304337
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004338 /* TODO remove this hardcoding and check why width is zero*/
4339 if (out->bit_width == 0)
4340 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304341 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004342 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304343 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304344 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304345 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004346 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4347 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4348 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004349 if(adev->primary_output == NULL)
4350 adev->primary_output = out;
4351 else {
4352 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004353 ret = -EEXIST;
4354 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004355 }
4356 }
4357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 /* Check if this usecase is already existing */
4359 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004360 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4361 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004364 ret = -EEXIST;
4365 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368 pthread_mutex_unlock(&adev->lock);
4369
4370 out->stream.common.get_sample_rate = out_get_sample_rate;
4371 out->stream.common.set_sample_rate = out_set_sample_rate;
4372 out->stream.common.get_buffer_size = out_get_buffer_size;
4373 out->stream.common.get_channels = out_get_channels;
4374 out->stream.common.get_format = out_get_format;
4375 out->stream.common.set_format = out_set_format;
4376 out->stream.common.standby = out_standby;
4377 out->stream.common.dump = out_dump;
4378 out->stream.common.set_parameters = out_set_parameters;
4379 out->stream.common.get_parameters = out_get_parameters;
4380 out->stream.common.add_audio_effect = out_add_audio_effect;
4381 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4382 out->stream.get_latency = out_get_latency;
4383 out->stream.set_volume = out_set_volume;
4384 out->stream.write = out_write;
4385 out->stream.get_render_position = out_get_render_position;
4386 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004387 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004389 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004391 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004392 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393
4394 config->format = out->stream.common.get_format(&out->stream.common);
4395 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4396 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4397
4398 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304399 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004400 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004401
4402 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4403 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4404 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004405 /* setup a channel for client <--> adsp communication for stream events */
4406 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
4407 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
4408 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4409 out->usecase, PCM_PLAYBACK);
4410 hdlr_stream_cfg.flags = out->flags;
4411 hdlr_stream_cfg.type = PCM_PLAYBACK;
4412 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4413 &hdlr_stream_cfg);
4414 if (ret) {
4415 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4416 out->adsp_hdlr_stream_handle = NULL;
4417 }
4418 }
Eric Laurent994a6932013-07-17 11:51:42 -07004419 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004421
4422error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304423 if (out->convert_buffer)
4424 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004425 free(out);
4426 *stream_out = NULL;
4427 ALOGD("%s: exit: ret %d", __func__, ret);
4428 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004429}
4430
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304431void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 struct audio_stream_out *stream)
4433{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004434 struct stream_out *out = (struct stream_out *)stream;
4435 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004436 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004437
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304438 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4439
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004440 /* close adsp hdrl session before standby */
4441 if (out->adsp_hdlr_stream_handle) {
4442 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4443 if (ret)
4444 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4445 out->adsp_hdlr_stream_handle = NULL;
4446 }
4447
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004448 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304449 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004450 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304451 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004452 if(ret != 0)
4453 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4454 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004455 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004456 out_standby(&stream->common);
4457
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004458 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004459 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004460 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004461 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004462 if (out->compr_config.codec != NULL)
4463 free(out->compr_config.codec);
4464 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004465
Ashish Jain83a6cc22016-06-28 14:34:17 +05304466 if (out->convert_buffer != NULL) {
4467 free(out->convert_buffer);
4468 out->convert_buffer = NULL;
4469 }
4470
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004471 if (adev->voice_tx_output == out)
4472 adev->voice_tx_output = NULL;
4473
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304474 if (adev->primary_output == out)
4475 adev->primary_output = NULL;
4476
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004477 pthread_cond_destroy(&out->cond);
4478 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004480 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481}
4482
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004483static void close_compress_sessions(struct audio_device *adev)
4484{
Mingming Yin7b762e72015-03-04 13:47:32 -08004485 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304486 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004487 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004488 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304489
4490 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004491 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304492 if (is_offload_usecase(usecase->id)) {
4493 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004494 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4495 out = usecase->stream.out;
4496 pthread_mutex_unlock(&adev->lock);
4497 out_standby(&out->stream.common);
4498 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004499 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004500 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304501 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004502 }
4503 pthread_mutex_unlock(&adev->lock);
4504}
4505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4507{
4508 struct audio_device *adev = (struct audio_device *)dev;
4509 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004510 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004511 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004512 int ret;
4513 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004515 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004516 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304518 if (!parms)
4519 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004520 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4521 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304522 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304523 if (strstr(snd_card_status, "OFFLINE")) {
4524 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304525 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004526 //close compress sessions on OFFLINE status
4527 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304528 } else if (strstr(snd_card_status, "ONLINE")) {
4529 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304530 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004531 //send dts hpx license if enabled
4532 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304533 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304534 }
4535
4536 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004537 status = voice_set_parameters(adev, parms);
4538 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004539 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004541 status = platform_set_parameters(adev->platform, parms);
4542 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004543 goto done;
4544
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004545 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4546 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004547 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4549 adev->bluetooth_nrec = true;
4550 else
4551 adev->bluetooth_nrec = false;
4552 }
4553
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004554 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4555 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4557 adev->screen_off = false;
4558 else
4559 adev->screen_off = true;
4560 }
4561
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004562 ret = str_parms_get_int(parms, "rotation", &val);
4563 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004564 bool reverse_speakers = false;
4565 switch(val) {
4566 // FIXME: note that the code below assumes that the speakers are in the correct placement
4567 // relative to the user when the device is rotated 90deg from its default rotation. This
4568 // assumption is device-specific, not platform-specific like this code.
4569 case 270:
4570 reverse_speakers = true;
4571 break;
4572 case 0:
4573 case 90:
4574 case 180:
4575 break;
4576 default:
4577 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004578 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004579 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004580 if (status == 0) {
4581 if (adev->speaker_lr_swap != reverse_speakers) {
4582 adev->speaker_lr_swap = reverse_speakers;
4583 // only update the selected device if there is active pcm playback
4584 struct audio_usecase *usecase;
4585 struct listnode *node;
4586 list_for_each(node, &adev->usecase_list) {
4587 usecase = node_to_item(node, struct audio_usecase, list);
4588 if (usecase->type == PCM_PLAYBACK) {
4589 select_devices(adev, usecase->id);
4590 break;
4591 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004592 }
4593 }
4594 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004595 }
4596
Mingming Yin514a8bc2014-07-29 15:22:21 -07004597 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4598 if (ret >= 0) {
4599 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4600 adev->bt_wb_speech_enabled = true;
4601 else
4602 adev->bt_wb_speech_enabled = false;
4603 }
4604
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004605 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4606 if (ret >= 0) {
4607 val = atoi(value);
4608 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004609 ALOGV("cache new ext disp type and edid");
4610 ret = platform_get_ext_disp_type(adev->platform);
4611 if (ret < 0) {
4612 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004613 status = ret;
4614 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004615 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004616 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004617 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004618 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004619 /*
4620 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4621 * Per AudioPolicyManager, USB device is higher priority than WFD.
4622 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4623 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4624 * starting voice call on USB
4625 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004626 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4627 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004628 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4629 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004630 }
vivek mehta344576a2016-04-12 18:56:03 -07004631 ALOGV("detected USB connect .. disable proxy");
4632 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004633 }
4634 }
4635
4636 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4637 if (ret >= 0) {
4638 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004639 /*
4640 * The HDMI / Displayport disconnect handling has been moved to
4641 * audio extension to ensure that its parameters are not
4642 * invalidated prior to updating sysfs of the disconnect event
4643 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4644 */
4645 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004646 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004647 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4648 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304649 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4650 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004651 }
vivek mehta344576a2016-04-12 18:56:03 -07004652 ALOGV("detected USB disconnect .. enable proxy");
4653 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004654 }
4655 }
4656
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304657 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4658 if (ret >= 0) {
4659 struct audio_usecase *usecase;
4660 struct listnode *node;
4661 list_for_each(node, &adev->usecase_list) {
4662 usecase = node_to_item(node, struct audio_usecase, list);
4663 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004664 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304665 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304666 lock_output_stream(usecase->stream.out);
4667 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304668 //force device switch to re configure encoder
4669 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304670 audio_extn_a2dp_set_handoff_mode(false);
4671 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304672 break;
4673 }
4674 }
4675 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004676
4677 //handle vr audio setparam
4678 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4679 value, sizeof(value));
4680 if (ret >= 0) {
4681 ALOGI("Setting vr mode to be %s", value);
4682 if (!strncmp(value, "true", 4)) {
4683 adev->vr_audio_mode_enabled = true;
4684 ALOGI("Setting vr mode to true");
4685 } else if (!strncmp(value, "false", 5)) {
4686 adev->vr_audio_mode_enabled = false;
4687 ALOGI("Setting vr mode to false");
4688 } else {
4689 ALOGI("wrong vr mode set");
4690 }
4691 }
4692
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304693 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004694done:
4695 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004696 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304697error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004698 ALOGV("%s: exit with code(%d)", __func__, status);
4699 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700}
4701
4702static char* adev_get_parameters(const struct audio_hw_device *dev,
4703 const char *keys)
4704{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004705 struct audio_device *adev = (struct audio_device *)dev;
4706 struct str_parms *reply = str_parms_create();
4707 struct str_parms *query = str_parms_create_str(keys);
4708 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304709 char value[256] = {0};
4710 int ret = 0;
4711
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004712 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004713 if (reply) {
4714 str_parms_destroy(reply);
4715 }
4716 if (query) {
4717 str_parms_destroy(query);
4718 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004719 ALOGE("adev_get_parameters: failed to create query or reply");
4720 return NULL;
4721 }
4722
Naresh Tannirud7205b62014-06-20 02:54:48 +05304723 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4724 sizeof(value));
4725 if (ret >=0) {
4726 int val = 1;
4727 pthread_mutex_lock(&adev->snd_card_status.lock);
4728 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4729 val = 0;
4730 pthread_mutex_unlock(&adev->snd_card_status.lock);
4731 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4732 goto exit;
4733 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004734 //handle vr audio getparam
4735
4736 ret = str_parms_get_str(query,
4737 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4738 value, sizeof(value));
4739
4740 if (ret >= 0) {
4741 bool vr_audio_enabled = false;
4742 pthread_mutex_lock(&adev->lock);
4743 vr_audio_enabled = adev->vr_audio_mode_enabled;
4744 pthread_mutex_unlock(&adev->lock);
4745
4746 ALOGI("getting vr mode to %d", vr_audio_enabled);
4747
4748 if (vr_audio_enabled) {
4749 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4750 "true");
4751 goto exit;
4752 } else {
4753 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4754 "false");
4755 goto exit;
4756 }
4757 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004758
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004759 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004760 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004761 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004762 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304763 pthread_mutex_unlock(&adev->lock);
4764
Naresh Tannirud7205b62014-06-20 02:54:48 +05304765exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004766 str = str_parms_to_str(reply);
4767 str_parms_destroy(query);
4768 str_parms_destroy(reply);
4769
4770 ALOGV("%s: exit: returns - %s", __func__, str);
4771 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772}
4773
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004774static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775{
4776 return 0;
4777}
4778
4779static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4780{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004781 int ret;
4782 struct audio_device *adev = (struct audio_device *)dev;
4783 pthread_mutex_lock(&adev->lock);
4784 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004785 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004786 pthread_mutex_unlock(&adev->lock);
4787 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788}
4789
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004790static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4791 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004792{
4793 return -ENOSYS;
4794}
4795
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004796static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4797 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004798{
4799 return -ENOSYS;
4800}
4801
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004802static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4803 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804{
4805 return -ENOSYS;
4806}
4807
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004808static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4809 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004810{
4811 return -ENOSYS;
4812}
4813
4814static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4815{
4816 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 pthread_mutex_lock(&adev->lock);
4819 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004820 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004822 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004823 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004824 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004825 adev->current_call_output = NULL;
4826 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827 }
4828 pthread_mutex_unlock(&adev->lock);
4829 return 0;
4830}
4831
4832static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4833{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004834 int ret;
4835
4836 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004837 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004838 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4839 pthread_mutex_unlock(&adev->lock);
4840
4841 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004842}
4843
4844static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4845{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004846 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847 return 0;
4848}
4849
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004850static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851 const struct audio_config *config)
4852{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004853 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004855 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4856 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857}
4858
4859static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004860 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861 audio_devices_t devices,
4862 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004863 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304864 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004865 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004866 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004867{
4868 struct audio_device *adev = (struct audio_device *)dev;
4869 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004870 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004871 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004872 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304873 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304876 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4877 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004878 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304879 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004880
4881 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004882
4883 if (!in) {
4884 ALOGE("failed to allocate input stream");
4885 return -ENOMEM;
4886 }
4887
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304888 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304889 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4890 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004891 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004892 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 in->stream.common.get_sample_rate = in_get_sample_rate;
4895 in->stream.common.set_sample_rate = in_set_sample_rate;
4896 in->stream.common.get_buffer_size = in_get_buffer_size;
4897 in->stream.common.get_channels = in_get_channels;
4898 in->stream.common.get_format = in_get_format;
4899 in->stream.common.set_format = in_set_format;
4900 in->stream.common.standby = in_standby;
4901 in->stream.common.dump = in_dump;
4902 in->stream.common.set_parameters = in_set_parameters;
4903 in->stream.common.get_parameters = in_get_parameters;
4904 in->stream.common.add_audio_effect = in_add_audio_effect;
4905 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4906 in->stream.set_gain = in_set_gain;
4907 in->stream.read = in_read;
4908 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4909
4910 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004911 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 in->standby = 1;
4914 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004915 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004916 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304918 in->usecase = USECASE_AUDIO_RECORD;
4919 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4920 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4921 is_low_latency = true;
4922#if LOW_LATENCY_CAPTURE_USE_CASE
4923 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4924#endif
4925 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4926 }
4927
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004928 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004929 if (in->realtime) {
4930 in->config = pcm_config_audio_capture_rt;
4931 in->sample_rate = in->config.rate;
4932 in->af_period_multiplier = af_period_multiplier;
4933 } else {
4934 in->config = pcm_config_audio_capture;
4935 in->config.rate = config->sample_rate;
4936 in->sample_rate = config->sample_rate;
4937 in->af_period_multiplier = 1;
4938 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304939 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004940
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304941 /* restrict 24 bit capture for unprocessed source only
4942 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4943 */
4944 if (config->format == AUDIO_FORMAT_DEFAULT) {
4945 config->format = AUDIO_FORMAT_PCM_16_BIT;
4946 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4947 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4948 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4949 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4950 bool ret_error = false;
4951 in->bit_width = 24;
4952 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4953 from HAL is 24_packed and 8_24
4954 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4955 24_packed return error indicating supported format is 24_packed
4956 *> In case of any other source requesting 24 bit or float return error
4957 indicating format supported is 16 bit only.
4958
4959 on error flinger will retry with supported format passed
4960 */
4961 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4962 (source != AUDIO_SOURCE_CAMCORDER)) {
4963 config->format = AUDIO_FORMAT_PCM_16_BIT;
4964 if (config->sample_rate > 48000)
4965 config->sample_rate = 48000;
4966 ret_error = true;
4967 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4968 in->config.format = PCM_FORMAT_S24_3LE;
4969 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4970 in->config.format = PCM_FORMAT_S24_LE;
4971 } else {
4972 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4973 ret_error = true;
4974 }
4975
4976 if (ret_error) {
4977 ret = -EINVAL;
4978 goto err_open;
4979 }
4980 }
4981
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304982 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304983 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4984 (adev->mode != AUDIO_MODE_IN_CALL)) {
4985 ret = -EINVAL;
4986 goto err_open;
4987 }
4988
4989 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4990 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004991 if (config->sample_rate == 0)
4992 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4993 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4994 config->sample_rate != 8000) {
4995 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4996 ret = -EINVAL;
4997 goto err_open;
4998 }
4999 if (config->format == AUDIO_FORMAT_DEFAULT)
5000 config->format = AUDIO_FORMAT_PCM_16_BIT;
5001 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5002 config->format = AUDIO_FORMAT_PCM_16_BIT;
5003 ret = -EINVAL;
5004 goto err_open;
5005 }
5006
5007 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5008 in->config = pcm_config_afe_proxy_record;
5009 in->config.channels = channel_count;
5010 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305011 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305012 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5013 in, config, &channel_mask_updated)) {
5014 if (channel_mask_updated == true) {
5015 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5016 __func__, config->channel_mask);
5017 ret = -EINVAL;
5018 goto err_open;
5019 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305020 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005021 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005022 audio_extn_compr_cap_format_supported(config->format) &&
5023 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005024 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305025 } else if (audio_extn_cin_applicable_stream(in)) {
5026 ret = audio_extn_cin_configure_input_stream(in);
5027 if (ret)
5028 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005029 } else {
5030 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005031 if (!in->realtime) {
5032 in->format = config->format;
5033 frame_size = audio_stream_in_frame_size(&in->stream);
5034 buffer_size = get_input_buffer_size(config->sample_rate,
5035 config->format,
5036 channel_count,
5037 is_low_latency);
5038 in->config.period_size = buffer_size / frame_size;
5039 }
5040
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005041 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005042 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005043 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005044 (in->config.rate == 8000 || in->config.rate == 16000 ||
5045 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005046 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5047 voice_extn_compress_voip_open_input_stream(in);
5048 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005049 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305051 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5052 &adev->streams_input_cfg_list,
5053 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305054 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305055
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005056 /* This stream could be for sound trigger lab,
5057 get sound trigger pcm if present */
5058 audio_extn_sound_trigger_check_and_get_session(in);
5059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005060 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005061 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005062 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005063
5064err_open:
5065 free(in);
5066 *stream_in = NULL;
5067 return ret;
5068}
5069
5070static void adev_close_input_stream(struct audio_hw_device *dev,
5071 struct audio_stream_in *stream)
5072{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005073 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005074 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005075 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305076
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305077 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005078
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305079 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005080 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305081
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005082 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305083 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005084 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305085 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005086 if (ret != 0)
5087 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5088 __func__, ret);
5089 } else
5090 in_standby(&stream->common);
5091
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005092 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005093 audio_extn_ssr_deinit();
5094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005095
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305096 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005097 audio_extn_compr_cap_format_supported(in->config.format))
5098 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305099
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305100 if (audio_extn_cin_attached_usecase(in->usecase))
5101 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005102
Mingming Yinfd7607b2016-01-22 12:48:44 -08005103 if (in->is_st_session) {
5104 ALOGV("%s: sound trigger pcm stop lab", __func__);
5105 audio_extn_sound_trigger_stop_lab(in);
5106 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005107 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108 return;
5109}
5110
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005111static int adev_dump(const audio_hw_device_t *device __unused,
5112 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113{
5114 return 0;
5115}
5116
5117static int adev_close(hw_device_t *device)
5118{
5119 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005120
5121 if (!adev)
5122 return 0;
5123
5124 pthread_mutex_lock(&adev_init_lock);
5125
5126 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005127 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005128 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305129 audio_extn_utils_release_streams_cfg_lists(
5130 &adev->streams_output_cfg_list,
5131 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305132 if (audio_extn_qaf_is_enabled())
5133 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005134 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005135 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005136 free(adev->snd_dev_ref_cnt);
5137 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005138 if (adev->adm_deinit)
5139 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305140 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005141 audio_extn_adsp_hdlr_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005142 free(device);
5143 adev = NULL;
5144 }
5145 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147 return 0;
5148}
5149
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005150/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5151 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5152 * just that it _might_ work.
5153 */
5154static int period_size_is_plausible_for_low_latency(int period_size)
5155{
5156 switch (period_size) {
5157 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005158 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005159 case 240:
5160 case 320:
5161 case 480:
5162 return 1;
5163 default:
5164 return 0;
5165 }
5166}
5167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005168static int adev_open(const hw_module_t *module, const char *name,
5169 hw_device_t **device)
5170{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305171 int ret;
5172
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005173 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005174 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5175
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005176 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005177 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005178 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005179 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005180 ALOGD("%s: returning existing instance of adev", __func__);
5181 ALOGD("%s: exit", __func__);
5182 pthread_mutex_unlock(&adev_init_lock);
5183 return 0;
5184 }
5185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005186 adev = calloc(1, sizeof(struct audio_device));
5187
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005188 if (!adev) {
5189 pthread_mutex_unlock(&adev_init_lock);
5190 return -ENOMEM;
5191 }
5192
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005193 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5194
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305195#ifdef DYNAMIC_LOG_ENABLED
5196 register_for_dynamic_logging("hal");
5197#endif
5198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005199 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5200 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5201 adev->device.common.module = (struct hw_module_t *)module;
5202 adev->device.common.close = adev_close;
5203
5204 adev->device.init_check = adev_init_check;
5205 adev->device.set_voice_volume = adev_set_voice_volume;
5206 adev->device.set_master_volume = adev_set_master_volume;
5207 adev->device.get_master_volume = adev_get_master_volume;
5208 adev->device.set_master_mute = adev_set_master_mute;
5209 adev->device.get_master_mute = adev_get_master_mute;
5210 adev->device.set_mode = adev_set_mode;
5211 adev->device.set_mic_mute = adev_set_mic_mute;
5212 adev->device.get_mic_mute = adev_get_mic_mute;
5213 adev->device.set_parameters = adev_set_parameters;
5214 adev->device.get_parameters = adev_get_parameters;
5215 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5216 adev->device.open_output_stream = adev_open_output_stream;
5217 adev->device.close_output_stream = adev_close_output_stream;
5218 adev->device.open_input_stream = adev_open_input_stream;
5219 adev->device.close_input_stream = adev_close_input_stream;
5220 adev->device.dump = adev_dump;
5221
5222 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005224 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005225 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005227 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005228 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005229 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005230 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005231 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005232 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005233 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005234 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005235 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305236 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305237 adev->perf_lock_opts[0] = 0x101;
5238 adev->perf_lock_opts[1] = 0x20E;
5239 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305240
5241 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5242 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005243 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005244 adev->platform = platform_init(adev);
5245 if (!adev->platform) {
5246 free(adev->snd_dev_ref_cnt);
5247 free(adev);
5248 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5249 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005250 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305251 pthread_mutex_destroy(&adev->lock);
5252 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005253 return -EINVAL;
5254 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005255
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305256 if (audio_extn_qaf_is_enabled()) {
5257 ret = audio_extn_qaf_init(adev);
5258 if (ret < 0) {
5259 free(adev);
5260 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5261 *device = NULL;
5262 pthread_mutex_unlock(&adev_init_lock);
5263 pthread_mutex_destroy(&adev->lock);
5264 return ret;
5265 }
5266
5267 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5268 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5269 }
5270
Naresh Tanniru4c630392014-05-12 01:05:52 +05305271 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5272
Eric Laurentc4aef752013-09-12 17:45:53 -07005273 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5274 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5275 if (adev->visualizer_lib == NULL) {
5276 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5277 } else {
5278 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5279 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005280 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005281 "visualizer_hal_start_output");
5282 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005283 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005284 "visualizer_hal_stop_output");
5285 }
5286 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305287 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005288 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005289 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005290 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005291
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005292 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5293 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5294 if (adev->offload_effects_lib == NULL) {
5295 ALOGE("%s: DLOPEN failed for %s", __func__,
5296 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5297 } else {
5298 ALOGV("%s: DLOPEN successful for %s", __func__,
5299 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5300 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305301 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005302 "offload_effects_bundle_hal_start_output");
5303 adev->offload_effects_stop_output =
5304 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5305 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005306 adev->offload_effects_set_hpx_state =
5307 (int (*)(bool))dlsym(adev->offload_effects_lib,
5308 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305309 adev->offload_effects_get_parameters =
5310 (void (*)(struct str_parms *, struct str_parms *))
5311 dlsym(adev->offload_effects_lib,
5312 "offload_effects_bundle_get_parameters");
5313 adev->offload_effects_set_parameters =
5314 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5315 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005316 }
5317 }
5318
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005319 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5320 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5321 if (adev->adm_lib == NULL) {
5322 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5323 } else {
5324 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5325 adev->adm_init = (adm_init_t)
5326 dlsym(adev->adm_lib, "adm_init");
5327 adev->adm_deinit = (adm_deinit_t)
5328 dlsym(adev->adm_lib, "adm_deinit");
5329 adev->adm_register_input_stream = (adm_register_input_stream_t)
5330 dlsym(adev->adm_lib, "adm_register_input_stream");
5331 adev->adm_register_output_stream = (adm_register_output_stream_t)
5332 dlsym(adev->adm_lib, "adm_register_output_stream");
5333 adev->adm_deregister_stream = (adm_deregister_stream_t)
5334 dlsym(adev->adm_lib, "adm_deregister_stream");
5335 adev->adm_request_focus = (adm_request_focus_t)
5336 dlsym(adev->adm_lib, "adm_request_focus");
5337 adev->adm_abandon_focus = (adm_abandon_focus_t)
5338 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005339 adev->adm_set_config = (adm_set_config_t)
5340 dlsym(adev->adm_lib, "adm_set_config");
5341 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5342 dlsym(adev->adm_lib, "adm_request_focus_v2");
5343 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5344 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5345 adev->adm_on_routing_change = (adm_on_routing_change_t)
5346 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005347 }
5348 }
5349
Mingming Yin514a8bc2014-07-29 15:22:21 -07005350 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005351 //initialize this to false for now,
5352 //this will be set to true through set param
5353 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005354
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005355 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356 *device = &adev->device.common;
5357
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305358 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5359 &adev->streams_output_cfg_list,
5360 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005361
Kiran Kandi910e1862013-10-29 13:29:42 -07005362 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005363
5364 char value[PROPERTY_VALUE_MAX];
5365 int trial;
5366 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5367 trial = atoi(value);
5368 if (period_size_is_plausible_for_low_latency(trial)) {
5369 pcm_config_low_latency.period_size = trial;
5370 pcm_config_low_latency.start_threshold = trial / 4;
5371 pcm_config_low_latency.avail_min = trial / 4;
5372 configured_low_latency_capture_period_size = trial;
5373 }
5374 }
5375 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5376 trial = atoi(value);
5377 if (period_size_is_plausible_for_low_latency(trial)) {
5378 configured_low_latency_capture_period_size = trial;
5379 }
5380 }
5381
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005382 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5383 af_period_multiplier = atoi(value);
5384 if (af_period_multiplier < 0)
5385 af_period_multiplier = 2;
5386 else if (af_period_multiplier > 4)
5387 af_period_multiplier = 4;
5388
5389 ALOGV("new period_multiplier = %d", af_period_multiplier);
5390 }
5391
vivek mehta446c3962015-09-14 10:57:35 -07005392 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005393 pthread_mutex_unlock(&adev_init_lock);
5394
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005395 if (adev->adm_init)
5396 adev->adm_data = adev->adm_init();
5397
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305398 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305399 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005400 audio_extn_adsp_hdlr_init(adev->mixer);
Eric Laurent994a6932013-07-17 11:51:42 -07005401 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005402 return 0;
5403}
5404
5405static struct hw_module_methods_t hal_module_methods = {
5406 .open = adev_open,
5407};
5408
5409struct audio_module HAL_MODULE_INFO_SYM = {
5410 .common = {
5411 .tag = HARDWARE_MODULE_TAG,
5412 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5413 .hal_api_version = HARDWARE_HAL_API_VERSION,
5414 .id = AUDIO_HARDWARE_MODULE_ID,
5415 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005416 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005417 .methods = &hal_module_methods,
5418 },
5419};