blob: 0b7812cd4175886d0432662cc508a0d940e16ceb [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,
1257 usecase->out_snd_device,
1258 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);
yidongh02ef86f2017-04-21 15:36:04 +08001544 if (usecase->stream.out != NULL) {
1545 out_snd_device_backend_match = platform_check_backends_match(
1546 voip_usecase->out_snd_device,
1547 platform_get_output_snd_device(
1548 adev->platform,
1549 usecase->stream.out));
1550 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001551 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001552 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1553 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001554 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001555 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001556 in_snd_device = voip_usecase->in_snd_device;
1557 out_snd_device = voip_usecase->out_snd_device;
1558 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001559 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001560 hfp_ucid = audio_extn_hfp_get_usecase();
1561 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001562 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001563 in_snd_device = hfp_usecase->in_snd_device;
1564 out_snd_device = hfp_usecase->out_snd_device;
1565 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 }
1567 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301568 if (usecase->stream.out == NULL) {
1569 ALOGE("%s: stream.out is NULL", __func__);
1570 return -EINVAL;
1571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 usecase->devices = usecase->stream.out->devices;
1573 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001574 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001575 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001576 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001577 if (usecase->stream.out == adev->primary_output &&
1578 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001579 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001580 select_devices(adev, adev->active_input->usecase);
1581 }
1582 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001583 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301584 if (usecase->stream.in == NULL) {
1585 ALOGE("%s: stream.in is NULL", __func__);
1586 return -EINVAL;
1587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588 usecase->devices = usecase->stream.in->device;
1589 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001590 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001591 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001592 if (adev->active_input &&
1593 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301594 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1595 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1596 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001597 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001598 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001599 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1600 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001601 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001602 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001603 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604 }
1605 }
1606
1607 if (out_snd_device == usecase->out_snd_device &&
1608 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301609
1610 if (!force_device_switch(usecase))
1611 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 }
1613
sangwoobc677242013-08-08 16:53:43 +09001614 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001615 out_snd_device, platform_get_snd_device_name(out_snd_device),
1616 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618 /*
1619 * Limitation: While in call, to do a device switch we need to disable
1620 * and enable both RX and TX devices though one of them is same as current
1621 * device.
1622 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001623 if ((usecase->type == VOICE_CALL) &&
1624 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1625 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001626 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001627 }
1628
1629 if (((usecase->type == VOICE_CALL) ||
1630 (usecase->type == VOIP_CALL)) &&
1631 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1632 /* Disable sidetone only if voice/voip call already exists */
1633 if (voice_is_call_state_active(adev) ||
1634 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001635 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001636
1637 /* Disable aanc only if voice call exists */
1638 if (voice_is_call_state_active(adev))
1639 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001640 }
1641
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001642 /* Disable current sound devices */
1643 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001644 disable_audio_route(adev, usecase);
1645 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 }
1647
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001649 disable_audio_route(adev, usecase);
1650 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001651 }
1652
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001653 /* Applicable only on the targets that has external modem.
1654 * New device information should be sent to modem before enabling
1655 * the devices to reduce in-call device switch time.
1656 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001657 if ((usecase->type == VOICE_CALL) &&
1658 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1659 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001660 status = platform_switch_voice_call_enable_device_config(adev->platform,
1661 out_snd_device,
1662 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001663 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001665 /* Enable new sound devices */
1666 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001667 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301668 if (platform_check_codec_asrc_support(adev->platform))
1669 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001670 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 }
1672
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001673 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301674 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001675 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001676 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677
Avinash Vaish71a8b972014-07-24 15:36:33 +05301678 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001679 status = platform_switch_voice_call_device_post(adev->platform,
1680 out_snd_device,
1681 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301682 enable_audio_route_for_voice_usecases(adev, usecase);
1683 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001684
sangwoo170731f2013-06-08 15:36:36 +09001685 usecase->in_snd_device = in_snd_device;
1686 usecase->out_snd_device = out_snd_device;
1687
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301688 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1689 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301690 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001691 if ((24 == usecase->stream.out->bit_width) &&
1692 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1693 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1694 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1695 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1696 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1697 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1698 /*
1699 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1700 * configured device sample rate, if not update the COPP rate to be equal to the
1701 * device sample rate, else open COPP at stream sample rate
1702 */
1703 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1704 usecase->stream.out->sample_rate,
1705 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301706 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1707 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001708 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1709 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1710 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1711 }
1712
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001713 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001714 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001715 audio_extn_gef_notify_device_config(
1716 usecase->stream.out->devices,
1717 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001718 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001719 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001720 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301721 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001722 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001723
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001724 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001725 /* Enable aanc only if voice call exists */
1726 if (voice_is_call_state_active(adev))
1727 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1728
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001729 /* Enable sidetone only if other voice/voip call already exists */
1730 if (voice_is_call_state_active(adev) ||
1731 voice_extn_compress_voip_is_started(adev))
1732 voice_set_sidetone(adev, out_snd_device, true);
1733 }
1734
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001735 /* Applicable only on the targets that has external modem.
1736 * Enable device command should be sent to modem only after
1737 * enabling voice call mixer controls
1738 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001739 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001740 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1741 out_snd_device,
1742 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301743 ALOGD("%s: done",__func__);
1744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 return status;
1746}
1747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748static int stop_input_stream(struct stream_in *in)
1749{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301750 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751 struct audio_usecase *uc_info;
1752 struct audio_device *adev = in->dev;
1753
Eric Laurent994a6932013-07-17 11:51:42 -07001754 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001755 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756 uc_info = get_usecase_from_list(adev, in->usecase);
1757 if (uc_info == NULL) {
1758 ALOGE("%s: Could not find the usecase (%d) in the list",
1759 __func__, in->usecase);
1760 return -EINVAL;
1761 }
1762
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001763 /* Close in-call recording streams */
1764 voice_check_and_stop_incall_rec_usecase(adev, in);
1765
Eric Laurent150dbfe2013-02-27 14:31:02 -08001766 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001767 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001768
1769 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001770 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001772 list_remove(&uc_info->list);
1773 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001775 adev->active_input = get_next_active_input(adev);
1776
Eric Laurent994a6932013-07-17 11:51:42 -07001777 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 return ret;
1779}
1780
1781int start_input_stream(struct stream_in *in)
1782{
1783 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001784 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 struct audio_usecase *uc_info;
1786 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301787 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788
Mingming Yin2664a5b2015-09-03 10:53:11 -07001789 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1790 if (get_usecase_from_list(adev, usecase) == NULL)
1791 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301792 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1793 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001794
Naresh Tanniru80659832014-06-04 18:17:56 +05301795
1796 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301797 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301798 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301799 goto error_config;
1800 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301801
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001802 /* Check if source matches incall recording usecase criteria */
1803 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1804 if (ret)
1805 goto error_config;
1806 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001807 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1808
1809 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1810 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1811 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001812 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001813 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001814
Eric Laurentb23d5282013-05-14 15:27:20 -07001815 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816 if (in->pcm_device_id < 0) {
1817 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1818 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001819 ret = -EINVAL;
1820 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822
1823 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001825
1826 if (!uc_info) {
1827 ret = -ENOMEM;
1828 goto error_config;
1829 }
1830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 uc_info->id = in->usecase;
1832 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001833 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001834 uc_info->devices = in->device;
1835 uc_info->in_snd_device = SND_DEVICE_NONE;
1836 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001838 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301839 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1840 adev->perf_lock_opts,
1841 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001842 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301844 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1845 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001846
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301847 if (audio_extn_cin_attached_usecase(in->usecase)) {
1848 ret = audio_extn_cin_start_input_stream(in);
1849 if (ret)
1850 goto error_open;
1851 else
1852 goto done_open;
1853 }
1854
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001855 unsigned int flags = PCM_IN;
1856 unsigned int pcm_open_retry_count = 0;
1857
1858 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1859 flags |= PCM_MMAP | PCM_NOIRQ;
1860 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001861 } else if (in->realtime) {
1862 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001863 }
1864
1865 while (1) {
1866 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1867 flags, &in->config);
1868 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1869 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1870 if (in->pcm != NULL) {
1871 pcm_close(in->pcm);
1872 in->pcm = NULL;
1873 }
1874 if (pcm_open_retry_count-- == 0) {
1875 ret = -EIO;
1876 goto error_open;
1877 }
1878 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1879 continue;
1880 }
1881 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001883
1884 ALOGV("%s: pcm_prepare", __func__);
1885 ret = pcm_prepare(in->pcm);
1886 if (ret < 0) {
1887 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1888 pcm_close(in->pcm);
1889 in->pcm = NULL;
1890 goto error_open;
1891 }
1892
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001893 register_in_stream(in);
1894 if (in->realtime) {
1895 ret = pcm_start(in->pcm);
1896 if (ret < 0)
1897 goto error_open;
1898 }
1899
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301900done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301901 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001902 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001903
Eric Laurentc8400632013-02-14 19:04:54 -08001904 return ret;
1905
1906error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301907 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001908 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001909error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301910 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301911 /*
1912 * sleep 50ms to allow sufficient time for kernel
1913 * drivers to recover incases like SSR.
1914 */
1915 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001916 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001917
1918 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001919}
1920
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001921void lock_input_stream(struct stream_in *in)
1922{
1923 pthread_mutex_lock(&in->pre_lock);
1924 pthread_mutex_lock(&in->lock);
1925 pthread_mutex_unlock(&in->pre_lock);
1926}
1927
1928void lock_output_stream(struct stream_out *out)
1929{
1930 pthread_mutex_lock(&out->pre_lock);
1931 pthread_mutex_lock(&out->lock);
1932 pthread_mutex_unlock(&out->pre_lock);
1933}
1934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001935/* must be called with out->lock locked */
1936static int send_offload_cmd_l(struct stream_out* out, int command)
1937{
1938 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1939
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001940 if (!cmd) {
1941 ALOGE("failed to allocate mem for command 0x%x", command);
1942 return -ENOMEM;
1943 }
1944
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001945 ALOGVV("%s %d", __func__, command);
1946
1947 cmd->cmd = command;
1948 list_add_tail(&out->offload_cmd_list, &cmd->node);
1949 pthread_cond_signal(&out->offload_cond);
1950 return 0;
1951}
1952
1953/* must be called iwth out->lock locked */
1954static void stop_compressed_output_l(struct stream_out *out)
1955{
1956 out->offload_state = OFFLOAD_STATE_IDLE;
1957 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001958 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001959 if (out->compr != NULL) {
1960 compress_stop(out->compr);
1961 while (out->offload_thread_blocked) {
1962 pthread_cond_wait(&out->cond, &out->lock);
1963 }
1964 }
1965}
1966
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001967bool is_offload_usecase(audio_usecase_t uc_id)
1968{
1969 unsigned int i;
1970 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1971 if (uc_id == offload_usecases[i])
1972 return true;
1973 }
1974 return false;
1975}
1976
Dhananjay Kumarac341582017-02-23 23:42:25 +05301977static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001978{
vivek mehta446c3962015-09-14 10:57:35 -07001979 audio_usecase_t ret_uc = USECASE_INVALID;
1980 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001981 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001982 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301983 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001984 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1985 else
1986 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001987
vivek mehta446c3962015-09-14 10:57:35 -07001988 pthread_mutex_lock(&adev->lock);
1989 if (get_usecase_from_list(adev, ret_uc) != NULL)
1990 ret_uc = USECASE_INVALID;
1991 pthread_mutex_unlock(&adev->lock);
1992
1993 return ret_uc;
1994 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001995
1996 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001997 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1998 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1999 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2000 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002001 break;
2002 }
2003 }
vivek mehta446c3962015-09-14 10:57:35 -07002004
2005 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2006 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002007}
2008
2009static void free_offload_usecase(struct audio_device *adev,
2010 audio_usecase_t uc_id)
2011{
vivek mehta446c3962015-09-14 10:57:35 -07002012 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002013 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002014
2015 if (!adev->multi_offload_enable)
2016 return;
2017
2018 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2019 if (offload_usecases[offload_uc_index] == uc_id) {
2020 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002021 break;
2022 }
2023 }
2024 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2025}
2026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027static void *offload_thread_loop(void *context)
2028{
2029 struct stream_out *out = (struct stream_out *) context;
2030 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002031 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2034 set_sched_policy(0, SP_FOREGROUND);
2035 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2036
2037 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002038 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039 for (;;) {
2040 struct offload_cmd *cmd = NULL;
2041 stream_callback_event_t event;
2042 bool send_callback = false;
2043
2044 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2045 __func__, list_empty(&out->offload_cmd_list),
2046 out->offload_state);
2047 if (list_empty(&out->offload_cmd_list)) {
2048 ALOGV("%s SLEEPING", __func__);
2049 pthread_cond_wait(&out->offload_cond, &out->lock);
2050 ALOGV("%s RUNNING", __func__);
2051 continue;
2052 }
2053
2054 item = list_head(&out->offload_cmd_list);
2055 cmd = node_to_item(item, struct offload_cmd, node);
2056 list_remove(item);
2057
2058 ALOGVV("%s STATE %d CMD %d out->compr %p",
2059 __func__, out->offload_state, cmd->cmd, out->compr);
2060
2061 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2062 free(cmd);
2063 break;
2064 }
2065
2066 if (out->compr == NULL) {
2067 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002068 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069 pthread_cond_signal(&out->cond);
2070 continue;
2071 }
2072 out->offload_thread_blocked = true;
2073 pthread_mutex_unlock(&out->lock);
2074 send_callback = false;
2075 switch(cmd->cmd) {
2076 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002077 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002079 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002080 send_callback = true;
2081 event = STREAM_CBK_EVENT_WRITE_READY;
2082 break;
2083 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002084 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302085 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002086 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302087 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002088 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302089 if (ret < 0)
2090 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302091 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302092 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002093 compress_drain(out->compr);
2094 else
2095 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302096 if (ret != -ENETRESET) {
2097 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302098 pthread_mutex_lock(&out->lock);
2099 out->send_new_metadata = 1;
2100 out->send_next_track_params = true;
2101 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302102 event = STREAM_CBK_EVENT_DRAIN_READY;
2103 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2104 } else
2105 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002106 break;
2107 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002108 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002109 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002110 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111 send_callback = true;
2112 event = STREAM_CBK_EVENT_DRAIN_READY;
2113 break;
2114 default:
2115 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2116 break;
2117 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002118 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 out->offload_thread_blocked = false;
2120 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002121 if (send_callback && out->client_callback) {
2122 ALOGVV("%s: sending client_callback event %d", __func__, event);
2123 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002124 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 free(cmd);
2126 }
2127
2128 pthread_cond_signal(&out->cond);
2129 while (!list_empty(&out->offload_cmd_list)) {
2130 item = list_head(&out->offload_cmd_list);
2131 list_remove(item);
2132 free(node_to_item(item, struct offload_cmd, node));
2133 }
2134 pthread_mutex_unlock(&out->lock);
2135
2136 return NULL;
2137}
2138
2139static int create_offload_callback_thread(struct stream_out *out)
2140{
2141 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2142 list_init(&out->offload_cmd_list);
2143 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2144 offload_thread_loop, out);
2145 return 0;
2146}
2147
2148static int destroy_offload_callback_thread(struct stream_out *out)
2149{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002150 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 stop_compressed_output_l(out);
2152 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2153
2154 pthread_mutex_unlock(&out->lock);
2155 pthread_join(out->offload_thread, (void **) NULL);
2156 pthread_cond_destroy(&out->offload_cond);
2157
2158 return 0;
2159}
2160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161static int stop_output_stream(struct stream_out *out)
2162{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302163 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 struct audio_usecase *uc_info;
2165 struct audio_device *adev = out->dev;
2166
Eric Laurent994a6932013-07-17 11:51:42 -07002167 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002168 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002169 uc_info = get_usecase_from_list(adev, out->usecase);
2170 if (uc_info == NULL) {
2171 ALOGE("%s: Could not find the usecase (%d) in the list",
2172 __func__, out->usecase);
2173 return -EINVAL;
2174 }
2175
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002176 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302177 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002178 if (adev->visualizer_stop_output != NULL)
2179 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002180
2181 audio_extn_dts_remove_state_notifier_node(out->usecase);
2182
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002183 if (adev->offload_effects_stop_output != NULL)
2184 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2185 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002186
Eric Laurent150dbfe2013-02-27 14:31:02 -08002187 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002188 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002189
2190 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002191 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002193 list_remove(&uc_info->list);
2194 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002196 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302197 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002198 ALOGV("Disable passthrough , reset mixer to pcm");
2199 /* NO_PASSTHROUGH */
2200 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002201 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002202 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2203 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002204
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302205 /* Must be called after removing the usecase from list */
2206 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302207 audio_extn_keep_alive_start();
2208
Manish Dewangan14956cc2017-02-14 18:54:42 +05302209 /*reset delay_param to 0*/
2210 out->delay_param.start_delay = 0;
2211
Eric Laurent994a6932013-07-17 11:51:42 -07002212 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213 return ret;
2214}
2215
2216int start_output_stream(struct stream_out *out)
2217{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 struct audio_usecase *uc_info;
2220 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302221 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002222 char mixer_ctl_name[128];
2223 struct mixer_ctl *ctl = NULL;
2224 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002226 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2227 ret = -EINVAL;
2228 goto error_config;
2229 }
2230
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302231 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2232 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2233 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302234
Naresh Tanniru80659832014-06-04 18:17:56 +05302235 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302236 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302237 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302238 goto error_config;
2239 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302240
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302241 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2242 if (!audio_extn_a2dp_is_ready()) {
2243 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2244 //combo usecase just by pass a2dp
2245 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2246 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2247 } else {
2248 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2249 ret = -EAGAIN;
2250 goto error_config;
2251 }
2252 }
2253 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002254 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 if (out->pcm_device_id < 0) {
2256 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2257 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002258 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002259 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 }
2261
2262 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002263
2264 if (!uc_info) {
2265 ret = -ENOMEM;
2266 goto error_config;
2267 }
2268
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269 uc_info->id = out->usecase;
2270 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002271 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002272 uc_info->devices = out->devices;
2273 uc_info->in_snd_device = SND_DEVICE_NONE;
2274 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002275 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302277 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2278 adev->perf_lock_opts,
2279 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302280
2281 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2282 audio_extn_keep_alive_stop();
2283 if (audio_extn_passthru_is_enabled() &&
2284 audio_extn_passthru_is_passthrough_stream(out)) {
2285 audio_extn_passthru_on_start(out);
2286 audio_extn_passthru_update_stream_configuration(adev, out);
2287 }
2288 }
2289
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002290 select_devices(adev, out->usecase);
2291
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002292 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2293 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002294 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002295 unsigned int flags = PCM_OUT;
2296 unsigned int pcm_open_retry_count = 0;
2297 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2298 flags |= PCM_MMAP | PCM_NOIRQ;
2299 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002300 } else if (out->realtime) {
2301 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002302 } else
2303 flags |= PCM_MONOTONIC;
2304
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002305 if ((adev->vr_audio_mode_enabled) &&
2306 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2307 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2308 "PCM_Dev %d Topology", out->pcm_device_id);
2309 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2310 if (!ctl) {
2311 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2312 __func__, mixer_ctl_name);
2313 } else {
2314 //if success use ULLPP
2315 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2316 __func__, mixer_ctl_name, out->pcm_device_id);
2317 //There is a still a possibility that some sessions
2318 // that request for FAST|RAW when 3D audio is active
2319 //can go through ULLPP. Ideally we expects apps to
2320 //listen to audio focus and stop concurrent playback
2321 //Also, we will look for mode flag (voice_in_communication)
2322 //before enabling the realtime flag.
2323 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2324 }
2325 }
2326
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002327 while (1) {
2328 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2329 flags, &out->config);
2330 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2331 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2332 if (out->pcm != NULL) {
2333 pcm_close(out->pcm);
2334 out->pcm = NULL;
2335 }
2336 if (pcm_open_retry_count-- == 0) {
2337 ret = -EIO;
2338 goto error_open;
2339 }
2340 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2341 continue;
2342 }
2343 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002345
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002346 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2347 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002348
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002349 ALOGV("%s: pcm_prepare", __func__);
2350 if (pcm_is_ready(out->pcm)) {
2351 ret = pcm_prepare(out->pcm);
2352 if (ret < 0) {
2353 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2354 pcm_close(out->pcm);
2355 out->pcm = NULL;
2356 goto error_open;
2357 }
2358 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302359 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2360 out->pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002362 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2363 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002365 out->compr = compress_open(adev->snd_card,
2366 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002367 COMPRESS_IN, &out->compr_config);
2368 if (out->compr && !is_compress_ready(out->compr)) {
2369 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2370 compress_close(out->compr);
2371 out->compr = NULL;
2372 ret = -EIO;
2373 goto error_open;
2374 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302375 /* compress_open sends params of the track, so reset the flag here */
2376 out->is_compr_metadata_avail = false;
2377
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002378 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002380
Fred Oh3f43e742015-03-04 18:42:34 -08002381 /* Since small bufs uses blocking writes, a write will be blocked
2382 for the default max poll time (20s) in the event of an SSR.
2383 Reduce the poll time to observe and deal with SSR faster.
2384 */
Ashish Jain5106d362016-05-11 19:23:33 +05302385 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002386 compress_set_max_poll_wait(out->compr, 1000);
2387 }
2388
Manish Dewangan69426c82017-01-30 17:35:36 +05302389 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302390 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan27346042017-03-01 12:56:12 +05302391 /* set render window if it was set before compress_open() */
2392 if (out->render_window.render_ws != 0 && out->render_window.render_we != 0)
2393 audio_extn_utils_compress_set_render_window(out,
2394 &out->render_window);
Manish Dewangan14956cc2017-02-14 18:54:42 +05302395 audio_extn_utils_compress_set_start_delay(out, &out->delay_param);
Manish Dewangan69426c82017-01-30 17:35:36 +05302396
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002397 audio_extn_dts_create_state_notifier_node(out->usecase);
2398 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2399 popcount(out->channel_mask),
2400 out->playback_started);
2401
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002402#ifdef DS1_DOLBY_DDP_ENABLED
2403 if (audio_extn_is_dolby_format(out->format))
2404 audio_extn_dolby_send_ddp_endp_params(adev);
2405#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302406 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2407 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002408 if (adev->visualizer_start_output != NULL)
2409 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2410 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302411 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002412 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002413 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002415
2416 if (ret == 0) {
2417 register_out_stream(out);
2418 if (out->realtime) {
2419 ret = pcm_start(out->pcm);
2420 if (ret < 0)
2421 goto error_open;
2422 }
2423 }
2424
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302425 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002426 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002427
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002428 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002429error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302430 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002432error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302433 /*
2434 * sleep 50ms to allow sufficient time for kernel
2435 * drivers to recover incases like SSR.
2436 */
2437 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002438 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439}
2440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441static int check_input_parameters(uint32_t sample_rate,
2442 audio_format_t format,
2443 int channel_count)
2444{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002445 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302447 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2448 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2449 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002450 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302451 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002452
2453 switch (channel_count) {
2454 case 1:
2455 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302456 case 3:
2457 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002458 case 6:
2459 break;
2460 default:
2461 ret = -EINVAL;
2462 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463
2464 switch (sample_rate) {
2465 case 8000:
2466 case 11025:
2467 case 12000:
2468 case 16000:
2469 case 22050:
2470 case 24000:
2471 case 32000:
2472 case 44100:
2473 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302474 case 96000:
2475 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 break;
2477 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002478 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 }
2480
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002481 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482}
2483
2484static size_t get_input_buffer_size(uint32_t sample_rate,
2485 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002486 int channel_count,
2487 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488{
2489 size_t size = 0;
2490
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002491 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2492 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002494 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002495 if (is_low_latency)
2496 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302497
2498 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002500 /* make sure the size is multiple of 32 bytes
2501 * At 48 kHz mono 16-bit PCM:
2502 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2503 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2504 */
2505 size += 0x1f;
2506 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002507
2508 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509}
2510
Ashish Jain058165c2016-09-28 23:18:48 +05302511static size_t get_output_period_size(uint32_t sample_rate,
2512 audio_format_t format,
2513 int channel_count,
2514 int duration /*in millisecs*/)
2515{
2516 size_t size = 0;
2517 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2518
2519 if ((duration == 0) || (sample_rate == 0) ||
2520 (bytes_per_sample == 0) || (channel_count == 0)) {
2521 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2522 bytes_per_sample, channel_count);
2523 return -EINVAL;
2524 }
2525
2526 size = (sample_rate *
2527 duration *
2528 bytes_per_sample *
2529 channel_count) / 1000;
2530 /*
2531 * To have same PCM samples for all channels, the buffer size requires to
2532 * be multiple of (number of channels * bytes per sample)
2533 * For writes to succeed, the buffer must be written at address which is multiple of 32
2534 */
2535 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2536
2537 return (size/(channel_count * bytes_per_sample));
2538}
2539
Ashish Jain5106d362016-05-11 19:23:33 +05302540static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2541{
2542 uint64_t actual_frames_rendered = 0;
2543 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2544
2545 /* This adjustment accounts for buffering after app processor.
2546 * It is based on estimated DSP latency per use case, rather than exact.
2547 */
2548 int64_t platform_latency = platform_render_latency(out->usecase) *
2549 out->sample_rate / 1000000LL;
2550
2551 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2552 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2553 * hence only estimate.
2554 */
2555 int64_t signed_frames = out->written - kernel_buffer_size;
2556
2557 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2558
2559 if (signed_frames > 0)
2560 actual_frames_rendered = signed_frames;
2561
2562 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2563 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2564 (long long int)out->written, (int)kernel_buffer_size,
2565 audio_bytes_per_sample(out->compr_config.codec->format),
2566 popcount(out->channel_mask));
2567
2568 return actual_frames_rendered;
2569}
2570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2572{
2573 struct stream_out *out = (struct stream_out *)stream;
2574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576}
2577
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002578static int out_set_sample_rate(struct audio_stream *stream __unused,
2579 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580{
2581 return -ENOSYS;
2582}
2583
2584static size_t out_get_buffer_size(const struct audio_stream *stream)
2585{
2586 struct stream_out *out = (struct stream_out *)stream;
2587
Dhananjay Kumarac341582017-02-23 23:42:25 +05302588 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002590 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2591 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302592 else if (is_offload_usecase(out->usecase) &&
2593 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302594 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002595
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002596 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002597 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598}
2599
2600static uint32_t out_get_channels(const struct audio_stream *stream)
2601{
2602 struct stream_out *out = (struct stream_out *)stream;
2603
2604 return out->channel_mask;
2605}
2606
2607static audio_format_t out_get_format(const struct audio_stream *stream)
2608{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002609 struct stream_out *out = (struct stream_out *)stream;
2610
2611 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612}
2613
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002614static int out_set_format(struct audio_stream *stream __unused,
2615 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616{
2617 return -ENOSYS;
2618}
2619
2620static int out_standby(struct audio_stream *stream)
2621{
2622 struct stream_out *out = (struct stream_out *)stream;
2623 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302625 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2626 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002628 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002630 if (adev->adm_deregister_stream)
2631 adev->adm_deregister_stream(adev->adm_data, out->handle);
2632
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002633 if (is_offload_usecase(out->usecase))
2634 stop_compressed_output_l(out);
2635
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002636 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002638 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2639 voice_extn_compress_voip_close_output_stream(stream);
2640 pthread_mutex_unlock(&adev->lock);
2641 pthread_mutex_unlock(&out->lock);
2642 ALOGD("VOIP output entered standby");
2643 return 0;
2644 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 if (out->pcm) {
2646 pcm_close(out->pcm);
2647 out->pcm = NULL;
2648 }
2649 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002650 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302651 out->send_next_track_params = false;
2652 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002653 out->gapless_mdata.encoder_delay = 0;
2654 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002655 if (out->compr != NULL) {
2656 compress_close(out->compr);
2657 out->compr = NULL;
2658 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002661 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 }
2663 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302664 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665 return 0;
2666}
2667
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002668static int out_dump(const struct audio_stream *stream __unused,
2669 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670{
2671 return 0;
2672}
2673
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002674static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2675{
2676 int ret = 0;
2677 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002678
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002679 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002680 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002681 return -EINVAL;
2682 }
2683
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302684 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002685
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002686 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2687 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302688 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002689 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002690 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2691 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302692 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002693 }
2694
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002695 ALOGV("%s new encoder delay %u and padding %u", __func__,
2696 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2697
2698 return 0;
2699}
2700
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002701static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2702{
2703 return out == adev->primary_output || out == adev->voice_tx_output;
2704}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2707{
2708 struct stream_out *out = (struct stream_out *)stream;
2709 struct audio_device *adev = out->dev;
2710 struct str_parms *parms;
2711 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002712 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713
sangwoobc677242013-08-08 16:53:43 +09002714 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002715 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302717 if (!parms)
2718 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002719 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2720 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002722 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002723 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002725 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002726 * When HDMI cable is unplugged the music playback is paused and
2727 * the policy manager sends routing=0. But the audioflinger continues
2728 * to write data until standby time (3sec). As the HDMI core is
2729 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002730 * Avoid this by routing audio to speaker until standby.
2731 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002732 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2733 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302734 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002735 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2736 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002737 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302738 /*
2739 * When A2DP is disconnected the
2740 * music playback is paused and the policy manager sends routing=0
2741 * But the audioflingercontinues to write data until standby time
2742 * (3sec). As BT is turned off, the write gets blocked.
2743 * Avoid this by routing audio to speaker until standby.
2744 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002745 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302746 (val == AUDIO_DEVICE_NONE)) {
2747 val = AUDIO_DEVICE_OUT_SPEAKER;
2748 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302749 /* To avoid a2dp to sco overlapping / BT device improper state
2750 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302751 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302752 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2753 if (!audio_extn_a2dp_is_ready()) {
2754 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2755 //combo usecase just by pass a2dp
2756 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2757 val = AUDIO_DEVICE_OUT_SPEAKER;
2758 } else {
2759 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2760 /* update device to a2dp and don't route as BT returned error
2761 * However it is still possible a2dp routing called because
2762 * of current active device disconnection (like wired headset)
2763 */
2764 out->devices = val;
2765 pthread_mutex_unlock(&out->lock);
2766 pthread_mutex_unlock(&adev->lock);
2767 goto error;
2768 }
2769 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302770 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002771 /*
2772 * select_devices() call below switches all the usecases on the same
2773 * backend to the new device. Refer to check_usecases_codec_backend() in
2774 * the select_devices(). But how do we undo this?
2775 *
2776 * For example, music playback is active on headset (deep-buffer usecase)
2777 * and if we go to ringtones and select a ringtone, low-latency usecase
2778 * will be started on headset+speaker. As we can't enable headset+speaker
2779 * and headset devices at the same time, select_devices() switches the music
2780 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2781 * So when the ringtone playback is completed, how do we undo the same?
2782 *
2783 * We are relying on the out_set_parameters() call on deep-buffer output,
2784 * once the ringtone playback is ended.
2785 * NOTE: We should not check if the current devices are same as new devices.
2786 * Because select_devices() must be called to switch back the music
2787 * playback to headset.
2788 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002789 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002790 audio_devices_t new_dev = val;
2791 bool same_dev = out->devices == new_dev;
2792 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002793
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002794 if (output_drives_call(adev, out)) {
2795 if(!voice_is_in_call(adev)) {
2796 if (adev->mode == AUDIO_MODE_IN_CALL) {
2797 adev->current_call_output = out;
2798 ret = voice_start_call(adev);
2799 }
2800 } else {
2801 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002802 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002803 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002804 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002805
2806 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002807 if (!same_dev) {
2808 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302809 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2810 adev->perf_lock_opts,
2811 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002812 if (adev->adm_on_routing_change)
2813 adev->adm_on_routing_change(adev->adm_data,
2814 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002815 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002816 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302817 if (!same_dev)
2818 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002819 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002820 }
2821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002823 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002825
2826 if (out == adev->primary_output) {
2827 pthread_mutex_lock(&adev->lock);
2828 audio_extn_set_parameters(adev, parms);
2829 pthread_mutex_unlock(&adev->lock);
2830 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002831 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002832 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002833 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002834
2835 audio_extn_dts_create_state_notifier_node(out->usecase);
2836 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2837 popcount(out->channel_mask),
2838 out->playback_started);
2839
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002840 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002841 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002842
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302843 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2844 if (err >= 0) {
2845 strlcpy(out->profile, value, sizeof(out->profile));
2846 ALOGV("updating stream profile with value '%s'", out->profile);
2847 lock_output_stream(out);
2848 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2849 &adev->streams_output_cfg_list,
2850 out->devices, out->flags, out->format,
2851 out->sample_rate, out->bit_width,
2852 out->channel_mask, out->profile,
2853 &out->app_type_cfg);
2854 pthread_mutex_unlock(&out->lock);
2855 }
2856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302858error:
Eric Laurent994a6932013-07-17 11:51:42 -07002859 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 return ret;
2861}
2862
2863static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2864{
2865 struct stream_out *out = (struct stream_out *)stream;
2866 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002867 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868 char value[256];
2869 struct str_parms *reply = str_parms_create();
2870 size_t i, j;
2871 int ret;
2872 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002873
2874 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002875 if (reply) {
2876 str_parms_destroy(reply);
2877 }
2878 if (query) {
2879 str_parms_destroy(query);
2880 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002881 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2882 return NULL;
2883 }
2884
Eric Laurent994a6932013-07-17 11:51:42 -07002885 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2887 if (ret >= 0) {
2888 value[0] = '\0';
2889 i = 0;
2890 while (out->supported_channel_masks[i] != 0) {
2891 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2892 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2893 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002894 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002896 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 first = false;
2898 break;
2899 }
2900 }
2901 i++;
2902 }
2903 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2904 str = str_parms_to_str(reply);
2905 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002906 voice_extn_out_get_parameters(out, query, reply);
2907 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002908 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002909 free(str);
2910 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002911 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002913
Alexy Joseph62142aa2015-11-16 15:10:34 -08002914
2915 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2916 if (ret >= 0) {
2917 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302918 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2919 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002920 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302921 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002922 } else {
2923 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302924 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002925 }
2926 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002927 if (str)
2928 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002929 str = str_parms_to_str(reply);
2930 }
2931
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002932 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2933 if (ret >= 0) {
2934 value[0] = '\0';
2935 i = 0;
2936 first = true;
2937 while (out->supported_formats[i] != 0) {
2938 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2939 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2940 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002941 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002942 }
2943 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2944 first = false;
2945 break;
2946 }
2947 }
2948 i++;
2949 }
2950 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002951 if (str)
2952 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002953 str = str_parms_to_str(reply);
2954 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002955
2956 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2957 if (ret >= 0) {
2958 value[0] = '\0';
2959 i = 0;
2960 first = true;
2961 while (out->supported_sample_rates[i] != 0) {
2962 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2963 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2964 if (!first) {
2965 strlcat(value, "|", sizeof(value));
2966 }
2967 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2968 first = false;
2969 break;
2970 }
2971 }
2972 i++;
2973 }
2974 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2975 if (str)
2976 free(str);
2977 str = str_parms_to_str(reply);
2978 }
2979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 str_parms_destroy(query);
2981 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002982 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 return str;
2984}
2985
2986static uint32_t out_get_latency(const struct audio_stream_out *stream)
2987{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002988 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002990 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991
Alexy Josephaa54c872014-12-03 02:46:47 -08002992 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302993 lock_output_stream(out);
2994 latency = audio_extn_utils_compress_get_dsp_latency(out);
2995 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002996 } else if (out->realtime) {
2997 // since the buffer won't be filled up faster than realtime,
2998 // return a smaller number
2999 if (out->config.rate)
3000 period_ms = (out->af_period_multiplier * out->config.period_size *
3001 1000) / (out->config.rate);
3002 else
3003 period_ms = 0;
3004 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003005 } else {
3006 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003007 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003008 }
3009
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003010 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3011 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3012 latency += audio_extn_a2dp_get_encoder_latency();
3013
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303014 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003015 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016}
3017
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303018static float AmpToDb(float amplification)
3019{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303020 float db = DSD_VOLUME_MIN_DB;
3021 if (amplification > 0) {
3022 db = 20 * log10(amplification);
3023 if(db < DSD_VOLUME_MIN_DB)
3024 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303025 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303026 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303027}
3028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029static int out_set_volume(struct audio_stream_out *stream, float left,
3030 float right)
3031{
Eric Laurenta9024de2013-04-04 09:19:12 -07003032 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003033 int volume[2];
3034
Eric Laurenta9024de2013-04-04 09:19:12 -07003035 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3036 /* only take left channel into account: the API is for stereo anyway */
3037 out->muted = (left == 0.0f);
3038 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003039 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303040 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003041 /*
3042 * Set mute or umute on HDMI passthrough stream.
3043 * Only take left channel into account.
3044 * Mute is 0 and unmute 1
3045 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303046 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303047 } else if (out->format == AUDIO_FORMAT_DSD){
3048 char mixer_ctl_name[128] = "DSD Volume";
3049 struct audio_device *adev = out->dev;
3050 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3051
3052 if (!ctl) {
3053 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3054 __func__, mixer_ctl_name);
3055 return -EINVAL;
3056 }
3057 volume[0] = (int)(AmpToDb(left));
3058 volume[1] = (int)(AmpToDb(right));
3059 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3060 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003061 } else {
3062 char mixer_ctl_name[128];
3063 struct audio_device *adev = out->dev;
3064 struct mixer_ctl *ctl;
3065 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003066 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003067
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003068 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3069 "Compress Playback %d Volume", pcm_device_id);
3070 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3071 if (!ctl) {
3072 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3073 __func__, mixer_ctl_name);
3074 return -EINVAL;
3075 }
3076 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3077 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3078 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3079 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003081 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 return -ENOSYS;
3084}
3085
3086static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3087 size_t bytes)
3088{
3089 struct stream_out *out = (struct stream_out *)stream;
3090 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303091 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003092 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003094 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303095
Naresh Tanniru80659832014-06-04 18:17:56 +05303096 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003097
Dhananjay Kumarac341582017-02-23 23:42:25 +05303098 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303099 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303100 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3101 pthread_mutex_unlock(&out->lock);
3102 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303103 } else {
3104 /* increase written size during SSR to avoid mismatch
3105 * with the written frames count in AF
3106 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003107 // bytes per frame
3108 size_t bpf = audio_bytes_per_sample(out->format) *
3109 audio_channel_count_from_out_mask(out->channel_mask);
3110 if (bpf != 0)
3111 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303112 ALOGD(" %s: sound card is not active/SSR state", __func__);
3113 ret= -EIO;
3114 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303115 }
3116 }
3117
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303118 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303119 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3120 if (audio_bytes_per_sample(out->format) != 0)
3121 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3122 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303123 goto exit;
3124 }
3125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003127 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003128 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003129 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3130 ret = voice_extn_compress_voip_start_output_stream(out);
3131 else
3132 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003133 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003134 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003136 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 goto exit;
3138 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003139
3140 if (last_known_cal_step != -1) {
3141 ALOGD("%s: retry previous failed cal level set", __func__);
3142 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3143 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145
Ashish Jain81eb2a82015-05-13 10:52:34 +05303146 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003147 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303148 adev->is_channel_status_set = true;
3149 }
3150
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003151 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003152 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003153 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003154 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003155 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3156 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303157 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3158 ALOGD("copl(%p):send next track params in gapless", out);
3159 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3160 out->send_next_track_params = false;
3161 out->is_compr_metadata_avail = false;
3162 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003163 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303164 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303165 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003166
Ashish Jain83a6cc22016-06-28 14:34:17 +05303167 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303168 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303169 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303170 pthread_mutex_unlock(&out->lock);
3171 return -EINVAL;
3172 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303173 audio_format_t dst_format = out->hal_op_format;
3174 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303175
3176 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3177 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3178
Ashish Jain83a6cc22016-06-28 14:34:17 +05303179 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303180 dst_format,
3181 buffer,
3182 src_format,
3183 frames);
3184
Ashish Jain83a6cc22016-06-28 14:34:17 +05303185 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303186 bytes_to_write);
3187
3188 /*Convert written bytes in audio flinger format*/
3189 if (ret > 0)
3190 ret = ((ret * format_to_bitwidth_table[out->format]) /
3191 format_to_bitwidth_table[dst_format]);
3192 }
3193 } else
3194 ret = compress_write(out->compr, buffer, bytes);
3195
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303196 if (ret < 0)
3197 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303198 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303199 /*msg to cb thread only if non blocking write is enabled*/
3200 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303201 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003202 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303203 } else if (-ENETRESET == ret) {
3204 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3205 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3206 pthread_mutex_unlock(&out->lock);
3207 out_standby(&out->stream.common);
3208 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003209 }
Ashish Jain5106d362016-05-11 19:23:33 +05303210 if ( ret == (ssize_t)bytes && !out->non_blocking)
3211 out->written += bytes;
3212
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303213 /* Call compr start only when non-zero bytes of data is there to be rendered */
3214 if (!out->playback_started && ret > 0) {
3215 int status = compress_start(out->compr);
3216 if (status < 0) {
3217 ret = status;
3218 ALOGE("%s: compr start failed with err %d", __func__, errno);
3219 goto exit;
3220 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003221 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003222 out->playback_started = 1;
3223 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003224
3225 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3226 popcount(out->channel_mask),
3227 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003228 }
3229 pthread_mutex_unlock(&out->lock);
3230 return ret;
3231 } else {
3232 if (out->pcm) {
3233 if (out->muted)
3234 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003235
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303236 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003237
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003238 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003239
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003240 if (out->config.rate)
3241 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3242 out->config.rate;
3243
3244 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3245
3246 request_out_focus(out, ns);
3247
3248 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003249 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003250 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303251 out->convert_buffer != NULL) {
3252
3253 memcpy_by_audio_format(out->convert_buffer,
3254 out->hal_op_format,
3255 buffer,
3256 out->hal_ip_format,
3257 out->config.period_size * out->config.channels);
3258
3259 ret = pcm_write(out->pcm, out->convert_buffer,
3260 (out->config.period_size *
3261 out->config.channels *
3262 format_to_bitwidth_table[out->hal_op_format]));
3263 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003264 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303265 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003266
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003267 release_out_focus(out);
3268
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303269 if (ret < 0)
3270 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303271 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3272 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3273 else
3274 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 }
3277
3278exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303279 /* ToDo: There may be a corner case when SSR happens back to back during
3280 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303281 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303282 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303283 }
3284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285 pthread_mutex_unlock(&out->lock);
3286
3287 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003288 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003289 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303290 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303291 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303292 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303293 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303294 out->standby = true;
3295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303297 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3298 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3299 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300 }
3301 return bytes;
3302}
3303
3304static int out_get_render_position(const struct audio_stream_out *stream,
3305 uint32_t *dsp_frames)
3306{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003307 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303308 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003309
3310 if (dsp_frames == NULL)
3311 return -EINVAL;
3312
3313 *dsp_frames = 0;
3314 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003315 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303316
3317 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3318 * this operation and adev_close_output_stream(where out gets reset).
3319 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303320 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303321 *dsp_frames = get_actual_pcm_frames_rendered(out);
3322 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3323 return 0;
3324 }
3325
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003326 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303327 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303328 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003329 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303330 if (ret < 0)
3331 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003332 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303333 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003334 }
3335 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303336 if (-ENETRESET == ret) {
3337 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3338 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3339 return -EINVAL;
3340 } else if(ret < 0) {
3341 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3342 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303343 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3344 /*
3345 * Handle corner case where compress session is closed during SSR
3346 * and timestamp is queried
3347 */
3348 ALOGE(" ERROR: sound card not active, return error");
3349 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303350 } else {
3351 return 0;
3352 }
Zhou Song32a556e2015-05-05 10:46:56 +08003353 } else if (audio_is_linear_pcm(out->format)) {
3354 *dsp_frames = out->written;
3355 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003356 } else
3357 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358}
3359
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003360static int out_add_audio_effect(const struct audio_stream *stream __unused,
3361 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362{
3363 return 0;
3364}
3365
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003366static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3367 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368{
3369 return 0;
3370}
3371
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003372static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3373 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374{
3375 return -EINVAL;
3376}
3377
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003378static int out_get_presentation_position(const struct audio_stream_out *stream,
3379 uint64_t *frames, struct timespec *timestamp)
3380{
3381 struct stream_out *out = (struct stream_out *)stream;
3382 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003383 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003384
Ashish Jain5106d362016-05-11 19:23:33 +05303385 /* below piece of code is not guarded against any lock because audioFliner serializes
3386 * this operation and adev_close_output_stream( where out gets reset).
3387 */
3388 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303389 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303390 *frames = get_actual_pcm_frames_rendered(out);
3391 /* this is the best we can do */
3392 clock_gettime(CLOCK_MONOTONIC, timestamp);
3393 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3394 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3395 return 0;
3396 }
3397
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003398 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003399
Ashish Jain5106d362016-05-11 19:23:33 +05303400 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3401 ret = compress_get_tstamp(out->compr, &dsp_frames,
3402 &out->sample_rate);
3403 ALOGVV("%s rendered frames %ld sample_rate %d",
3404 __func__, dsp_frames, out->sample_rate);
3405 *frames = dsp_frames;
3406 if (ret < 0)
3407 ret = -errno;
3408 if (-ENETRESET == ret) {
3409 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3410 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3411 ret = -EINVAL;
3412 } else
3413 ret = 0;
3414 /* this is the best we can do */
3415 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003416 } else {
3417 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003418 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003419 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3420 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003421 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003422 // This adjustment accounts for buffering after app processor.
3423 // It is based on estimated DSP latency per use case, rather than exact.
3424 signed_frames -=
3425 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3426
Eric Laurent949a0892013-09-20 09:20:13 -07003427 // It would be unusual for this value to be negative, but check just in case ...
3428 if (signed_frames >= 0) {
3429 *frames = signed_frames;
3430 ret = 0;
3431 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003432 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303433 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3434 *frames = out->written;
3435 clock_gettime(CLOCK_MONOTONIC, timestamp);
3436 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003437 }
3438 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003439 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003440 return ret;
3441}
3442
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443static int out_set_callback(struct audio_stream_out *stream,
3444 stream_callback_t callback, void *cookie)
3445{
3446 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003447 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448
3449 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003450 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003451 out->client_callback = callback;
3452 out->client_cookie = cookie;
3453 if (out->adsp_hdlr_stream_handle) {
3454 ret = audio_extn_adsp_hdlr_stream_set_callback(
3455 out->adsp_hdlr_stream_handle,
3456 callback,
3457 cookie);
3458 if (ret)
3459 ALOGW("%s:adsp hdlr callback registration failed %d",
3460 __func__, ret);
3461 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003462 pthread_mutex_unlock(&out->lock);
3463 return 0;
3464}
3465
3466static int out_pause(struct audio_stream_out* stream)
3467{
3468 struct stream_out *out = (struct stream_out *)stream;
3469 int status = -ENOSYS;
3470 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003471 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003472 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003473 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303475 struct audio_device *adev = out->dev;
3476 int snd_scard_state = get_snd_card_state(adev);
3477
3478 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3479 status = compress_pause(out->compr);
3480
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003482
Mingming Yin21854652016-04-13 11:54:02 -07003483 if (audio_extn_passthru_is_active()) {
3484 ALOGV("offload use case, pause passthru");
3485 audio_extn_passthru_on_pause(out);
3486 }
3487
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303488 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003489 audio_extn_dts_notify_playback_state(out->usecase, 0,
3490 out->sample_rate, popcount(out->channel_mask),
3491 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003492 }
3493 pthread_mutex_unlock(&out->lock);
3494 }
3495 return status;
3496}
3497
3498static int out_resume(struct audio_stream_out* stream)
3499{
3500 struct stream_out *out = (struct stream_out *)stream;
3501 int status = -ENOSYS;
3502 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003503 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003504 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003505 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003506 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003507 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303508 struct audio_device *adev = out->dev;
3509 int snd_scard_state = get_snd_card_state(adev);
3510
Mingming Yin21854652016-04-13 11:54:02 -07003511 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3512 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3513 pthread_mutex_lock(&out->dev->lock);
3514 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003515 pthread_mutex_unlock(&out->dev->lock);
3516 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303517 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003518 }
3519 if (!status) {
3520 out->offload_state = OFFLOAD_STATE_PLAYING;
3521 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303522 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003523 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3524 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525 }
3526 pthread_mutex_unlock(&out->lock);
3527 }
3528 return status;
3529}
3530
3531static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3532{
3533 struct stream_out *out = (struct stream_out *)stream;
3534 int status = -ENOSYS;
3535 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003536 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003537 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003538 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3539 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3540 else
3541 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3542 pthread_mutex_unlock(&out->lock);
3543 }
3544 return status;
3545}
3546
3547static int out_flush(struct audio_stream_out* stream)
3548{
3549 struct stream_out *out = (struct stream_out *)stream;
3550 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003551 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003552 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003553 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003554 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3555 stop_compressed_output_l(out);
3556 out->written = 0;
3557 } else {
3558 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3559 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003560 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003561 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003562 return 0;
3563 }
3564 return -ENOSYS;
3565}
3566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567/** audio_stream_in implementation **/
3568static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3569{
3570 struct stream_in *in = (struct stream_in *)stream;
3571
3572 return in->config.rate;
3573}
3574
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003575static int in_set_sample_rate(struct audio_stream *stream __unused,
3576 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577{
3578 return -ENOSYS;
3579}
3580
3581static size_t in_get_buffer_size(const struct audio_stream *stream)
3582{
3583 struct stream_in *in = (struct stream_in *)stream;
3584
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003585 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3586 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003587 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3588 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303589 else if(audio_extn_cin_attached_usecase(in->usecase))
3590 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003591
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003592 return in->config.period_size * in->af_period_multiplier *
3593 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003594}
3595
3596static uint32_t in_get_channels(const struct audio_stream *stream)
3597{
3598 struct stream_in *in = (struct stream_in *)stream;
3599
3600 return in->channel_mask;
3601}
3602
3603static audio_format_t in_get_format(const struct audio_stream *stream)
3604{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003605 struct stream_in *in = (struct stream_in *)stream;
3606
3607 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608}
3609
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003610static int in_set_format(struct audio_stream *stream __unused,
3611 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612{
3613 return -ENOSYS;
3614}
3615
3616static int in_standby(struct audio_stream *stream)
3617{
3618 struct stream_in *in = (struct stream_in *)stream;
3619 struct audio_device *adev = in->dev;
3620 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303621 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3622 stream, in->usecase, use_case_table[in->usecase]);
3623
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003624 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003625 if (!in->standby && in->is_st_session) {
3626 ALOGD("%s: sound trigger pcm stop lab", __func__);
3627 audio_extn_sound_trigger_stop_lab(in);
3628 in->standby = 1;
3629 }
3630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003632 if (adev->adm_deregister_stream)
3633 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3634
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003635 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003637 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3638 voice_extn_compress_voip_close_input_stream(stream);
3639 ALOGD("VOIP input entered standby");
3640 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303641 if (audio_extn_cin_attached_usecase(in->usecase))
3642 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003643 if (in->pcm) {
3644 pcm_close(in->pcm);
3645 in->pcm = NULL;
3646 }
3647 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003648 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003649 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003650 }
3651 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003652 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653 return status;
3654}
3655
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003656static int in_dump(const struct audio_stream *stream __unused,
3657 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658{
3659 return 0;
3660}
3661
3662static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3663{
3664 struct stream_in *in = (struct stream_in *)stream;
3665 struct audio_device *adev = in->dev;
3666 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003668 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303670 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 parms = str_parms_create_str(kvpairs);
3672
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303673 if (!parms)
3674 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003675 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003676 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003677
3678 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3679 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680 val = atoi(value);
3681 /* no audio source uses val == 0 */
3682 if ((in->source != val) && (val != 0)) {
3683 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003684 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3685 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3686 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003687 (in->config.rate == 8000 || in->config.rate == 16000 ||
3688 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003689 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003690 err = voice_extn_compress_voip_open_input_stream(in);
3691 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003692 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003693 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003694 }
3695 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 }
3697 }
3698
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003699 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3700 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003702 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703 in->device = val;
3704 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003705 if (!in->standby && !in->is_st_session) {
3706 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003707 if (adev->adm_on_routing_change)
3708 adev->adm_on_routing_change(adev->adm_data,
3709 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003710 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003711 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712 }
3713 }
3714
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303715 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3716 if (err >= 0) {
3717 strlcpy(in->profile, value, sizeof(in->profile));
3718 ALOGV("updating stream profile with value '%s'", in->profile);
3719 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3720 &adev->streams_input_cfg_list,
3721 in->device, in->flags, in->format,
3722 in->sample_rate, in->bit_width,
3723 in->profile, &in->app_type_cfg);
3724 }
3725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003727 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728
3729 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303730error:
Eric Laurent994a6932013-07-17 11:51:42 -07003731 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 return ret;
3733}
3734
3735static char* in_get_parameters(const struct audio_stream *stream,
3736 const char *keys)
3737{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003738 struct stream_in *in = (struct stream_in *)stream;
3739 struct str_parms *query = str_parms_create_str(keys);
3740 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003741 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003742
3743 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003744 if (reply) {
3745 str_parms_destroy(reply);
3746 }
3747 if (query) {
3748 str_parms_destroy(query);
3749 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003750 ALOGE("in_get_parameters: failed to create query or reply");
3751 return NULL;
3752 }
3753
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003754 ALOGV("%s: enter: keys - %s", __func__, keys);
3755
3756 voice_extn_in_get_parameters(in, query, reply);
3757
3758 str = str_parms_to_str(reply);
3759 str_parms_destroy(query);
3760 str_parms_destroy(reply);
3761
3762 ALOGV("%s: exit: returns - %s", __func__, str);
3763 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764}
3765
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003766static int in_set_gain(struct audio_stream_in *stream __unused,
3767 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768{
3769 return 0;
3770}
3771
3772static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3773 size_t bytes)
3774{
3775 struct stream_in *in = (struct stream_in *)stream;
3776 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303777 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303778 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303779 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003781 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303782
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003783 if (in->is_st_session) {
3784 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3785 /* Read from sound trigger HAL */
3786 audio_extn_sound_trigger_read(in, buffer, bytes);
3787 pthread_mutex_unlock(&in->lock);
3788 return bytes;
3789 }
3790
Ashish Jainbbce4322016-02-16 13:25:27 +05303791 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003792 ALOGD(" %s: sound card is not active/SSR state", __func__);
3793 ret= -EIO;;
3794 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303795 }
3796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003798 pthread_mutex_lock(&adev->lock);
3799 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3800 ret = voice_extn_compress_voip_start_input_stream(in);
3801 else
3802 ret = start_input_stream(in);
3803 pthread_mutex_unlock(&adev->lock);
3804 if (ret != 0) {
3805 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 }
3807 in->standby = 0;
3808 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003810 // what's the duration requested by the client?
3811 long ns = 0;
3812
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303813 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003814 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3815 in->config.rate;
3816
3817 request_in_focus(in, ns);
3818 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003819
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303820 if (audio_extn_cin_attached_usecase(in->usecase)) {
3821 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3822 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303823 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003824 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303825 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003826 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003827 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003828 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303829 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003830 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303831 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3832 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3833 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3834 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303835 ret = -EINVAL;
3836 goto exit;
3837 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303838 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303839 ret = -errno;
3840 }
3841 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303842 /* bytes read is always set to bytes for non compress usecases */
3843 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 }
3845
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003846 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 /*
3849 * Instead of writing zeroes here, we could trust the hardware
3850 * to always provide zeroes when muted.
3851 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303852 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3853 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 memset(buffer, 0, bytes);
3855
3856exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303857 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303858 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003859 if (-ENETRESET == ret)
3860 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 pthread_mutex_unlock(&in->lock);
3863
3864 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303865 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303866 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303867 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303868 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303869 in->standby = true;
3870 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303871 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3872 bytes_read = bytes;
3873 memset(buffer, 0, bytes);
3874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003875 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003876 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303877 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303878 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303880 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881}
3882
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003883static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884{
3885 return 0;
3886}
3887
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003888static int add_remove_audio_effect(const struct audio_stream *stream,
3889 effect_handle_t effect,
3890 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003892 struct stream_in *in = (struct stream_in *)stream;
3893 int status = 0;
3894 effect_descriptor_t desc;
3895
3896 status = (*effect)->get_descriptor(effect, &desc);
3897 if (status != 0)
3898 return status;
3899
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003900 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003901 pthread_mutex_lock(&in->dev->lock);
3902 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3903 in->enable_aec != enable &&
3904 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3905 in->enable_aec = enable;
3906 if (!in->standby)
3907 select_devices(in->dev, in->usecase);
3908 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003909 if (in->enable_ns != enable &&
3910 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3911 in->enable_ns = enable;
3912 if (!in->standby)
3913 select_devices(in->dev, in->usecase);
3914 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003915 pthread_mutex_unlock(&in->dev->lock);
3916 pthread_mutex_unlock(&in->lock);
3917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918 return 0;
3919}
3920
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003921static int in_add_audio_effect(const struct audio_stream *stream,
3922 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923{
Eric Laurent994a6932013-07-17 11:51:42 -07003924 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003925 return add_remove_audio_effect(stream, effect, true);
3926}
3927
3928static int in_remove_audio_effect(const struct audio_stream *stream,
3929 effect_handle_t effect)
3930{
Eric Laurent994a6932013-07-17 11:51:42 -07003931 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003932 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933}
3934
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303935int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 audio_io_handle_t handle,
3937 audio_devices_t devices,
3938 audio_output_flags_t flags,
3939 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003940 struct audio_stream_out **stream_out,
3941 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942{
3943 struct audio_device *adev = (struct audio_device *)dev;
3944 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303945 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003946 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003947 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303950
3951 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3952 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003953 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303954 return -EINVAL;
3955 }
3956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3958
Mingming Yin3a941d42016-02-17 18:08:05 -08003959 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3960 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303961 devices, flags, &out->stream);
3962
3963
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003964 if (!out) {
3965 return -ENOMEM;
3966 }
3967
Haynes Mathew George204045b2015-02-25 20:32:03 -08003968 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003969 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003970 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 if (devices == AUDIO_DEVICE_NONE)
3973 devices = AUDIO_DEVICE_OUT_SPEAKER;
3974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975 out->flags = flags;
3976 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003977 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003978 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003979 out->sample_rate = config->sample_rate;
3980 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3981 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003982 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003983 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003984 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303985 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986
Mingming Yin3a941d42016-02-17 18:08:05 -08003987 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3988 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3989 pthread_mutex_lock(&adev->lock);
3990 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3991 ret = read_hdmi_sink_caps(out);
3992 pthread_mutex_unlock(&adev->lock);
3993 if (ret != 0) {
3994 if (ret == -ENOSYS) {
3995 /* ignore and go with default */
3996 ret = 0;
3997 } else {
3998 ALOGE("error reading hdmi sink caps");
3999 goto error_open;
4000 }
4001 }
4002 }
4003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304005 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004006 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004007 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004008 ret = voice_extn_compress_voip_open_output_stream(out);
4009 if (ret != 0) {
4010 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4011 __func__, ret);
4012 goto error_open;
4013 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004014 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304015 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004016
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004017 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4018 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4019 ALOGE("%s: Unsupported Offload information", __func__);
4020 ret = -EINVAL;
4021 goto error_open;
4022 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004023
Mingming Yin3a941d42016-02-17 18:08:05 -08004024 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004025 if(config->offload_info.format == 0)
4026 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004027 if (config->offload_info.sample_rate == 0)
4028 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004029 }
4030
Mingming Yin90310102013-11-13 16:57:00 -08004031 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304032 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004033 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004034 ret = -EINVAL;
4035 goto error_open;
4036 }
4037
4038 out->compr_config.codec = (struct snd_codec *)
4039 calloc(1, sizeof(struct snd_codec));
4040
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004041 if (!out->compr_config.codec) {
4042 ret = -ENOMEM;
4043 goto error_open;
4044 }
4045
Dhananjay Kumarac341582017-02-23 23:42:25 +05304046 out->stream.pause = out_pause;
4047 out->stream.resume = out_resume;
4048 out->stream.flush = out_flush;
4049 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004050 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004051 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304052 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004053 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304054 } else {
4055 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4056 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004057 }
vivek mehta446c3962015-09-14 10:57:35 -07004058
4059 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004060 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4061 config->format == 0 && config->sample_rate == 0 &&
4062 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004063 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004064 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4065 } else {
4066 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4067 ret = -EEXIST;
4068 goto error_open;
4069 }
vivek mehta446c3962015-09-14 10:57:35 -07004070 }
4071
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 if (config->offload_info.channel_mask)
4073 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004074 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004075 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004076 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004077 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304078 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004079 ret = -EINVAL;
4080 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004081 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004082
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004083 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004084 out->sample_rate = config->offload_info.sample_rate;
4085
Mingming Yin3ee55c62014-08-04 14:23:35 -07004086 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004087
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304088 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4089 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4090 audio_extn_dolby_send_ddp_endp_params(adev);
4091 audio_extn_dolby_set_dmid(adev);
4092 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004094 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004095 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004096 out->compr_config.codec->bit_rate =
4097 config->offload_info.bit_rate;
4098 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304099 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004100 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304101 /* Update bit width only for non passthrough usecases.
4102 * For passthrough usecases, the output will always be opened @16 bit
4103 */
4104 if (!audio_extn_passthru_is_passthrough_stream(out))
4105 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004106 /*TODO: Do we need to change it for passthrough */
4107 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004108
Manish Dewangana6fc5442015-08-24 20:30:31 +05304109 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4110 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304111 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304112 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304113 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4114 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304115
4116 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4117 AUDIO_FORMAT_PCM) {
4118
4119 /*Based on platform support, configure appropriate alsa format for corresponding
4120 *hal input format.
4121 */
4122 out->compr_config.codec->format = hal_format_to_alsa(
4123 config->offload_info.format);
4124
Ashish Jain83a6cc22016-06-28 14:34:17 +05304125 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304126 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304127 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304128
Dhananjay Kumarac341582017-02-23 23:42:25 +05304129 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304130 *hal input format and alsa format might differ based on platform support.
4131 */
4132 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304133 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304134
4135 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4136
4137 /* Check if alsa session is configured with the same format as HAL input format,
4138 * if not then derive correct fragment size needed to accomodate the
4139 * conversion of HAL input format to alsa format.
4140 */
4141 audio_extn_utils_update_direct_pcm_fragment_size(out);
4142
4143 /*if hal input and output fragment size is different this indicates HAL input format is
4144 *not same as the alsa format
4145 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304146 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304147 /*Allocate a buffer to convert input data to the alsa configured format.
4148 *size of convert buffer is equal to the size required to hold one fragment size
4149 *worth of pcm data, this is because flinger does not write more than fragment_size
4150 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304151 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4152 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304153 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4154 ret = -ENOMEM;
4155 goto error_open;
4156 }
4157 }
4158 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4159 out->compr_config.fragment_size =
4160 audio_extn_passthru_get_buffer_size(&config->offload_info);
4161 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4162 } else {
4163 out->compr_config.fragment_size =
4164 platform_get_compress_offload_buffer_size(&config->offload_info);
4165 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4166 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004167
Amit Shekhar6f461b12014-08-01 14:52:58 -07004168 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304169 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004170
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304171 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4172 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4173 }
4174
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004175 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4176 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004177
Manish Dewangan69426c82017-01-30 17:35:36 +05304178 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4179 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4180 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4181 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4182 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4183 } else {
4184 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4185 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004186
Manish Dewangan27346042017-03-01 12:56:12 +05304187 memset(&out->render_window, 0,
4188 sizeof(struct audio_out_render_window_param));
4189
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004190 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304191 out->send_next_track_params = false;
4192 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004193 out->offload_state = OFFLOAD_STATE_IDLE;
4194 out->playback_started = 0;
4195
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004196 audio_extn_dts_create_state_notifier_node(out->usecase);
4197
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004198 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4199 __func__, config->offload_info.version,
4200 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304201
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304202 /* Check if DSD audio format is supported in codec
4203 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304204 */
4205
4206 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304207 (!platform_check_codec_dsd_support(adev->platform) ||
4208 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304209 ret = -EINVAL;
4210 goto error_open;
4211 }
4212
Ashish Jain5106d362016-05-11 19:23:33 +05304213 /* Disable gapless if any of the following is true
4214 * passthrough playback
4215 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304216 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304217 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304218 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304219 (config->format == AUDIO_FORMAT_DSD) ||
4220 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304221 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304222 check_and_set_gapless_mode(adev, false);
4223 } else
4224 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004225
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304226 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004227 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4228 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304229 if (config->format == AUDIO_FORMAT_DSD) {
4230 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4231 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4232 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004233
4234 create_offload_callback_thread(out);
4235
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004236 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304237 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004238 if (ret != 0) {
4239 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4240 __func__, ret);
4241 goto error_open;
4242 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004243 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4244 if (config->sample_rate == 0)
4245 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4246 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4247 config->sample_rate != 8000) {
4248 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4249 ret = -EINVAL;
4250 goto error_open;
4251 }
4252 out->sample_rate = config->sample_rate;
4253 out->config.rate = config->sample_rate;
4254 if (config->format == AUDIO_FORMAT_DEFAULT)
4255 config->format = AUDIO_FORMAT_PCM_16_BIT;
4256 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4257 config->format = AUDIO_FORMAT_PCM_16_BIT;
4258 ret = -EINVAL;
4259 goto error_open;
4260 }
4261 out->format = config->format;
4262 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4263 out->config = pcm_config_afe_proxy_playback;
4264 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004265 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304266 unsigned int channels = 0;
4267 /*Update config params to default if not set by the caller*/
4268 if (config->sample_rate == 0)
4269 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4270 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4271 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4272 if (config->format == AUDIO_FORMAT_DEFAULT)
4273 config->format = AUDIO_FORMAT_PCM_16_BIT;
4274
4275 channels = audio_channel_count_from_out_mask(out->channel_mask);
4276
Ashish Jain83a6cc22016-06-28 14:34:17 +05304277 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4278 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004279 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4280 out->flags);
4281 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304282 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4283 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4284 out->config = pcm_config_low_latency;
4285 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4286 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4287 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304288 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4289 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4290 if (out->config.period_size <= 0) {
4291 ALOGE("Invalid configuration period size is not valid");
4292 ret = -EINVAL;
4293 goto error_open;
4294 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304295 } else {
4296 /* primary path is the default path selected if no other outputs are available/suitable */
4297 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4298 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4299 }
4300 out->hal_ip_format = format = out->format;
4301 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4302 out->hal_op_format = pcm_format_to_hal(out->config.format);
4303 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4304 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004305 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304306 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304307 if (out->hal_ip_format != out->hal_op_format) {
4308 uint32_t buffer_size = out->config.period_size *
4309 format_to_bitwidth_table[out->hal_op_format] *
4310 out->config.channels;
4311 out->convert_buffer = calloc(1, buffer_size);
4312 if (out->convert_buffer == NULL){
4313 ALOGE("Allocation failed for convert buffer for size %d",
4314 out->compr_config.fragment_size);
4315 ret = -ENOMEM;
4316 goto error_open;
4317 }
4318 ALOGD("Convert buffer allocated of size %d", buffer_size);
4319 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004320 }
4321
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004322 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4323 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304324
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004325 /* TODO remove this hardcoding and check why width is zero*/
4326 if (out->bit_width == 0)
4327 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304328 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004329 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304330 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304331 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304332 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004333 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4334 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4335 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004336 if(adev->primary_output == NULL)
4337 adev->primary_output = out;
4338 else {
4339 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004340 ret = -EEXIST;
4341 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004342 }
4343 }
4344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345 /* Check if this usecase is already existing */
4346 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004347 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4348 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004351 ret = -EEXIST;
4352 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355 pthread_mutex_unlock(&adev->lock);
4356
4357 out->stream.common.get_sample_rate = out_get_sample_rate;
4358 out->stream.common.set_sample_rate = out_set_sample_rate;
4359 out->stream.common.get_buffer_size = out_get_buffer_size;
4360 out->stream.common.get_channels = out_get_channels;
4361 out->stream.common.get_format = out_get_format;
4362 out->stream.common.set_format = out_set_format;
4363 out->stream.common.standby = out_standby;
4364 out->stream.common.dump = out_dump;
4365 out->stream.common.set_parameters = out_set_parameters;
4366 out->stream.common.get_parameters = out_get_parameters;
4367 out->stream.common.add_audio_effect = out_add_audio_effect;
4368 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4369 out->stream.get_latency = out_get_latency;
4370 out->stream.set_volume = out_set_volume;
4371 out->stream.write = out_write;
4372 out->stream.get_render_position = out_get_render_position;
4373 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004374 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004376 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004378 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004379 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
4381 config->format = out->stream.common.get_format(&out->stream.common);
4382 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4383 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4384
4385 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304386 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004387 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004388
4389 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4390 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4391 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004392 /* setup a channel for client <--> adsp communication for stream events */
4393 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
4394 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
4395 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4396 out->usecase, PCM_PLAYBACK);
4397 hdlr_stream_cfg.flags = out->flags;
4398 hdlr_stream_cfg.type = PCM_PLAYBACK;
4399 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4400 &hdlr_stream_cfg);
4401 if (ret) {
4402 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4403 out->adsp_hdlr_stream_handle = NULL;
4404 }
4405 }
Eric Laurent994a6932013-07-17 11:51:42 -07004406 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004407 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004408
4409error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304410 if (out->convert_buffer)
4411 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004412 free(out);
4413 *stream_out = NULL;
4414 ALOGD("%s: exit: ret %d", __func__, ret);
4415 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416}
4417
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304418void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419 struct audio_stream_out *stream)
4420{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004421 struct stream_out *out = (struct stream_out *)stream;
4422 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004423 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004424
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304425 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4426
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004427 /* close adsp hdrl session before standby */
4428 if (out->adsp_hdlr_stream_handle) {
4429 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4430 if (ret)
4431 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4432 out->adsp_hdlr_stream_handle = NULL;
4433 }
4434
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004435 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304436 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004437 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304438 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004439 if(ret != 0)
4440 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4441 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004442 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004443 out_standby(&stream->common);
4444
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004445 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004446 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004447 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004448 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004449 if (out->compr_config.codec != NULL)
4450 free(out->compr_config.codec);
4451 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004452
Ashish Jain83a6cc22016-06-28 14:34:17 +05304453 if (out->convert_buffer != NULL) {
4454 free(out->convert_buffer);
4455 out->convert_buffer = NULL;
4456 }
4457
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004458 if (adev->voice_tx_output == out)
4459 adev->voice_tx_output = NULL;
4460
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304461 if (adev->primary_output == out)
4462 adev->primary_output = NULL;
4463
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004464 pthread_cond_destroy(&out->cond);
4465 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004467 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468}
4469
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004470static void close_compress_sessions(struct audio_device *adev)
4471{
Mingming Yin7b762e72015-03-04 13:47:32 -08004472 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304473 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004474 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004475 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304476
4477 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004478 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304479 if (is_offload_usecase(usecase->id)) {
4480 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004481 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4482 out = usecase->stream.out;
4483 pthread_mutex_unlock(&adev->lock);
4484 out_standby(&out->stream.common);
4485 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004486 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004487 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304488 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004489 }
4490 pthread_mutex_unlock(&adev->lock);
4491}
4492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4494{
4495 struct audio_device *adev = (struct audio_device *)dev;
4496 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004498 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004499 int ret;
4500 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004501
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004502 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304505 if (!parms)
4506 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004507 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4508 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304509 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304510 if (strstr(snd_card_status, "OFFLINE")) {
4511 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304512 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004513 //close compress sessions on OFFLINE status
4514 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304515 } else if (strstr(snd_card_status, "ONLINE")) {
4516 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304517 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004518 //send dts hpx license if enabled
4519 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304520 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304521 }
4522
4523 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004524 status = voice_set_parameters(adev, parms);
4525 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004526 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004527
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004528 status = platform_set_parameters(adev->platform, parms);
4529 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004530 goto done;
4531
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004532 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4533 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004534 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4536 adev->bluetooth_nrec = true;
4537 else
4538 adev->bluetooth_nrec = false;
4539 }
4540
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004541 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4542 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4544 adev->screen_off = false;
4545 else
4546 adev->screen_off = true;
4547 }
4548
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004549 ret = str_parms_get_int(parms, "rotation", &val);
4550 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004551 bool reverse_speakers = false;
4552 switch(val) {
4553 // FIXME: note that the code below assumes that the speakers are in the correct placement
4554 // relative to the user when the device is rotated 90deg from its default rotation. This
4555 // assumption is device-specific, not platform-specific like this code.
4556 case 270:
4557 reverse_speakers = true;
4558 break;
4559 case 0:
4560 case 90:
4561 case 180:
4562 break;
4563 default:
4564 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004565 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004566 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004567 if (status == 0) {
4568 if (adev->speaker_lr_swap != reverse_speakers) {
4569 adev->speaker_lr_swap = reverse_speakers;
4570 // only update the selected device if there is active pcm playback
4571 struct audio_usecase *usecase;
4572 struct listnode *node;
4573 list_for_each(node, &adev->usecase_list) {
4574 usecase = node_to_item(node, struct audio_usecase, list);
4575 if (usecase->type == PCM_PLAYBACK) {
4576 select_devices(adev, usecase->id);
4577 break;
4578 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004579 }
4580 }
4581 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004582 }
4583
Mingming Yin514a8bc2014-07-29 15:22:21 -07004584 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4585 if (ret >= 0) {
4586 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4587 adev->bt_wb_speech_enabled = true;
4588 else
4589 adev->bt_wb_speech_enabled = false;
4590 }
4591
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004592 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4593 if (ret >= 0) {
4594 val = atoi(value);
4595 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004596 ALOGV("cache new ext disp type and edid");
4597 ret = platform_get_ext_disp_type(adev->platform);
4598 if (ret < 0) {
4599 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004600 status = ret;
4601 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004602 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004603 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004604 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004605 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004606 /*
4607 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4608 * Per AudioPolicyManager, USB device is higher priority than WFD.
4609 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4610 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4611 * starting voice call on USB
4612 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004613 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4614 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004615 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4616 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004617 }
vivek mehta344576a2016-04-12 18:56:03 -07004618 ALOGV("detected USB connect .. disable proxy");
4619 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004620 }
4621 }
4622
4623 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4624 if (ret >= 0) {
4625 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004626 /*
4627 * The HDMI / Displayport disconnect handling has been moved to
4628 * audio extension to ensure that its parameters are not
4629 * invalidated prior to updating sysfs of the disconnect event
4630 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4631 */
4632 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004633 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004634 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4635 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304636 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4637 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004638 }
vivek mehta344576a2016-04-12 18:56:03 -07004639 ALOGV("detected USB disconnect .. enable proxy");
4640 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004641 }
4642 }
4643
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304644 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4645 if (ret >= 0) {
4646 struct audio_usecase *usecase;
4647 struct listnode *node;
4648 list_for_each(node, &adev->usecase_list) {
4649 usecase = node_to_item(node, struct audio_usecase, list);
4650 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004651 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304652 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304653 lock_output_stream(usecase->stream.out);
4654 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304655 //force device switch to re configure encoder
4656 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304657 audio_extn_a2dp_set_handoff_mode(false);
4658 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304659 break;
4660 }
4661 }
4662 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004663
4664 //handle vr audio setparam
4665 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4666 value, sizeof(value));
4667 if (ret >= 0) {
4668 ALOGI("Setting vr mode to be %s", value);
4669 if (!strncmp(value, "true", 4)) {
4670 adev->vr_audio_mode_enabled = true;
4671 ALOGI("Setting vr mode to true");
4672 } else if (!strncmp(value, "false", 5)) {
4673 adev->vr_audio_mode_enabled = false;
4674 ALOGI("Setting vr mode to false");
4675 } else {
4676 ALOGI("wrong vr mode set");
4677 }
4678 }
4679
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304680 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004681done:
4682 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004683 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304684error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004685 ALOGV("%s: exit with code(%d)", __func__, status);
4686 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687}
4688
4689static char* adev_get_parameters(const struct audio_hw_device *dev,
4690 const char *keys)
4691{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004692 struct audio_device *adev = (struct audio_device *)dev;
4693 struct str_parms *reply = str_parms_create();
4694 struct str_parms *query = str_parms_create_str(keys);
4695 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304696 char value[256] = {0};
4697 int ret = 0;
4698
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004699 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004700 if (reply) {
4701 str_parms_destroy(reply);
4702 }
4703 if (query) {
4704 str_parms_destroy(query);
4705 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004706 ALOGE("adev_get_parameters: failed to create query or reply");
4707 return NULL;
4708 }
4709
Naresh Tannirud7205b62014-06-20 02:54:48 +05304710 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4711 sizeof(value));
4712 if (ret >=0) {
4713 int val = 1;
4714 pthread_mutex_lock(&adev->snd_card_status.lock);
4715 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4716 val = 0;
4717 pthread_mutex_unlock(&adev->snd_card_status.lock);
4718 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4719 goto exit;
4720 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004721 //handle vr audio getparam
4722
4723 ret = str_parms_get_str(query,
4724 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4725 value, sizeof(value));
4726
4727 if (ret >= 0) {
4728 bool vr_audio_enabled = false;
4729 pthread_mutex_lock(&adev->lock);
4730 vr_audio_enabled = adev->vr_audio_mode_enabled;
4731 pthread_mutex_unlock(&adev->lock);
4732
4733 ALOGI("getting vr mode to %d", vr_audio_enabled);
4734
4735 if (vr_audio_enabled) {
4736 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4737 "true");
4738 goto exit;
4739 } else {
4740 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4741 "false");
4742 goto exit;
4743 }
4744 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004745
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004746 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004747 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004748 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004749 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304750 pthread_mutex_unlock(&adev->lock);
4751
Naresh Tannirud7205b62014-06-20 02:54:48 +05304752exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004753 str = str_parms_to_str(reply);
4754 str_parms_destroy(query);
4755 str_parms_destroy(reply);
4756
4757 ALOGV("%s: exit: returns - %s", __func__, str);
4758 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004759}
4760
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004761static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762{
4763 return 0;
4764}
4765
4766static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4767{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004768 int ret;
4769 struct audio_device *adev = (struct audio_device *)dev;
4770 pthread_mutex_lock(&adev->lock);
4771 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004772 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004773 pthread_mutex_unlock(&adev->lock);
4774 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775}
4776
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004777static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4778 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004779{
4780 return -ENOSYS;
4781}
4782
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004783static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4784 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785{
4786 return -ENOSYS;
4787}
4788
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004789static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4790 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004791{
4792 return -ENOSYS;
4793}
4794
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004795static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4796 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797{
4798 return -ENOSYS;
4799}
4800
4801static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4802{
4803 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805 pthread_mutex_lock(&adev->lock);
4806 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004807 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004808 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004809 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004810 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004811 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004812 adev->current_call_output = NULL;
4813 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814 }
4815 pthread_mutex_unlock(&adev->lock);
4816 return 0;
4817}
4818
4819static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4820{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004821 int ret;
4822
4823 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004824 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004825 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4826 pthread_mutex_unlock(&adev->lock);
4827
4828 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004829}
4830
4831static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4832{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004833 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834 return 0;
4835}
4836
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004837static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004838 const struct audio_config *config)
4839{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004840 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004842 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4843 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844}
4845
4846static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004847 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848 audio_devices_t devices,
4849 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004850 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304851 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004852 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004853 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854{
4855 struct audio_device *adev = (struct audio_device *)dev;
4856 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004857 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004858 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004859 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304860 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004862 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304863 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4864 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304866 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004867
4868 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004869
4870 if (!in) {
4871 ALOGE("failed to allocate input stream");
4872 return -ENOMEM;
4873 }
4874
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304875 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304876 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4877 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004878 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004879 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004881 in->stream.common.get_sample_rate = in_get_sample_rate;
4882 in->stream.common.set_sample_rate = in_set_sample_rate;
4883 in->stream.common.get_buffer_size = in_get_buffer_size;
4884 in->stream.common.get_channels = in_get_channels;
4885 in->stream.common.get_format = in_get_format;
4886 in->stream.common.set_format = in_set_format;
4887 in->stream.common.standby = in_standby;
4888 in->stream.common.dump = in_dump;
4889 in->stream.common.set_parameters = in_set_parameters;
4890 in->stream.common.get_parameters = in_get_parameters;
4891 in->stream.common.add_audio_effect = in_add_audio_effect;
4892 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4893 in->stream.set_gain = in_set_gain;
4894 in->stream.read = in_read;
4895 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4896
4897 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004898 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004899 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004900 in->standby = 1;
4901 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004902 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004903 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004904
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304905 in->usecase = USECASE_AUDIO_RECORD;
4906 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4907 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4908 is_low_latency = true;
4909#if LOW_LATENCY_CAPTURE_USE_CASE
4910 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4911#endif
4912 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4913 }
4914
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004915 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004916 if (in->realtime) {
4917 in->config = pcm_config_audio_capture_rt;
4918 in->sample_rate = in->config.rate;
4919 in->af_period_multiplier = af_period_multiplier;
4920 } else {
4921 in->config = pcm_config_audio_capture;
4922 in->config.rate = config->sample_rate;
4923 in->sample_rate = config->sample_rate;
4924 in->af_period_multiplier = 1;
4925 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304926 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304928 /* restrict 24 bit capture for unprocessed source only
4929 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4930 */
4931 if (config->format == AUDIO_FORMAT_DEFAULT) {
4932 config->format = AUDIO_FORMAT_PCM_16_BIT;
4933 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4934 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4935 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4936 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4937 bool ret_error = false;
4938 in->bit_width = 24;
4939 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4940 from HAL is 24_packed and 8_24
4941 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4942 24_packed return error indicating supported format is 24_packed
4943 *> In case of any other source requesting 24 bit or float return error
4944 indicating format supported is 16 bit only.
4945
4946 on error flinger will retry with supported format passed
4947 */
4948 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4949 (source != AUDIO_SOURCE_CAMCORDER)) {
4950 config->format = AUDIO_FORMAT_PCM_16_BIT;
4951 if (config->sample_rate > 48000)
4952 config->sample_rate = 48000;
4953 ret_error = true;
4954 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4955 in->config.format = PCM_FORMAT_S24_3LE;
4956 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4957 in->config.format = PCM_FORMAT_S24_LE;
4958 } else {
4959 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4960 ret_error = true;
4961 }
4962
4963 if (ret_error) {
4964 ret = -EINVAL;
4965 goto err_open;
4966 }
4967 }
4968
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304969 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304970 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4971 (adev->mode != AUDIO_MODE_IN_CALL)) {
4972 ret = -EINVAL;
4973 goto err_open;
4974 }
4975
4976 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4977 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004978 if (config->sample_rate == 0)
4979 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4980 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4981 config->sample_rate != 8000) {
4982 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4983 ret = -EINVAL;
4984 goto err_open;
4985 }
4986 if (config->format == AUDIO_FORMAT_DEFAULT)
4987 config->format = AUDIO_FORMAT_PCM_16_BIT;
4988 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4989 config->format = AUDIO_FORMAT_PCM_16_BIT;
4990 ret = -EINVAL;
4991 goto err_open;
4992 }
4993
4994 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4995 in->config = pcm_config_afe_proxy_record;
4996 in->config.channels = channel_count;
4997 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304998 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304999 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5000 in, config, &channel_mask_updated)) {
5001 if (channel_mask_updated == true) {
5002 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5003 __func__, config->channel_mask);
5004 ret = -EINVAL;
5005 goto err_open;
5006 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305007 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005008 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005009 audio_extn_compr_cap_format_supported(config->format) &&
5010 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005011 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305012 } else if (audio_extn_cin_applicable_stream(in)) {
5013 ret = audio_extn_cin_configure_input_stream(in);
5014 if (ret)
5015 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005016 } else {
5017 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005018 if (!in->realtime) {
5019 in->format = config->format;
5020 frame_size = audio_stream_in_frame_size(&in->stream);
5021 buffer_size = get_input_buffer_size(config->sample_rate,
5022 config->format,
5023 channel_count,
5024 is_low_latency);
5025 in->config.period_size = buffer_size / frame_size;
5026 }
5027
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005028 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005029 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005030 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005031 (in->config.rate == 8000 || in->config.rate == 16000 ||
5032 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005033 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5034 voice_extn_compress_voip_open_input_stream(in);
5035 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005036 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305038 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5039 &adev->streams_input_cfg_list,
5040 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305041 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305042
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005043 /* This stream could be for sound trigger lab,
5044 get sound trigger pcm if present */
5045 audio_extn_sound_trigger_check_and_get_session(in);
5046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005048 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005049 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050
5051err_open:
5052 free(in);
5053 *stream_in = NULL;
5054 return ret;
5055}
5056
5057static void adev_close_input_stream(struct audio_hw_device *dev,
5058 struct audio_stream_in *stream)
5059{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005060 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005061 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005062 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305063
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305064 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005065
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305066 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005067 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305068
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005069 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305070 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005071 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305072 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005073 if (ret != 0)
5074 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5075 __func__, ret);
5076 } else
5077 in_standby(&stream->common);
5078
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005079 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005080 audio_extn_ssr_deinit();
5081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005082
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305083 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005084 audio_extn_compr_cap_format_supported(in->config.format))
5085 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305086
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305087 if (audio_extn_cin_attached_usecase(in->usecase))
5088 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005089
Mingming Yinfd7607b2016-01-22 12:48:44 -08005090 if (in->is_st_session) {
5091 ALOGV("%s: sound trigger pcm stop lab", __func__);
5092 audio_extn_sound_trigger_stop_lab(in);
5093 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005094 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005095 return;
5096}
5097
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005098static int adev_dump(const audio_hw_device_t *device __unused,
5099 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100{
5101 return 0;
5102}
5103
5104static int adev_close(hw_device_t *device)
5105{
5106 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005107
5108 if (!adev)
5109 return 0;
5110
5111 pthread_mutex_lock(&adev_init_lock);
5112
5113 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005114 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005115 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305116 audio_extn_utils_release_streams_cfg_lists(
5117 &adev->streams_output_cfg_list,
5118 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305119 if (audio_extn_qaf_is_enabled())
5120 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005121 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005122 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005123 free(adev->snd_dev_ref_cnt);
5124 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005125 if (adev->adm_deinit)
5126 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305127 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005128 audio_extn_adsp_hdlr_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005129 free(device);
5130 adev = NULL;
5131 }
5132 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134 return 0;
5135}
5136
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005137/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5138 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5139 * just that it _might_ work.
5140 */
5141static int period_size_is_plausible_for_low_latency(int period_size)
5142{
5143 switch (period_size) {
5144 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005145 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005146 case 240:
5147 case 320:
5148 case 480:
5149 return 1;
5150 default:
5151 return 0;
5152 }
5153}
5154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005155static int adev_open(const hw_module_t *module, const char *name,
5156 hw_device_t **device)
5157{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305158 int ret;
5159
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005160 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005161 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5162
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005163 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005164 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005165 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005166 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005167 ALOGD("%s: returning existing instance of adev", __func__);
5168 ALOGD("%s: exit", __func__);
5169 pthread_mutex_unlock(&adev_init_lock);
5170 return 0;
5171 }
5172
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005173 adev = calloc(1, sizeof(struct audio_device));
5174
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005175 if (!adev) {
5176 pthread_mutex_unlock(&adev_init_lock);
5177 return -ENOMEM;
5178 }
5179
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005180 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5181
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305182#ifdef DYNAMIC_LOG_ENABLED
5183 register_for_dynamic_logging("hal");
5184#endif
5185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005186 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5187 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5188 adev->device.common.module = (struct hw_module_t *)module;
5189 adev->device.common.close = adev_close;
5190
5191 adev->device.init_check = adev_init_check;
5192 adev->device.set_voice_volume = adev_set_voice_volume;
5193 adev->device.set_master_volume = adev_set_master_volume;
5194 adev->device.get_master_volume = adev_get_master_volume;
5195 adev->device.set_master_mute = adev_set_master_mute;
5196 adev->device.get_master_mute = adev_get_master_mute;
5197 adev->device.set_mode = adev_set_mode;
5198 adev->device.set_mic_mute = adev_set_mic_mute;
5199 adev->device.get_mic_mute = adev_get_mic_mute;
5200 adev->device.set_parameters = adev_set_parameters;
5201 adev->device.get_parameters = adev_get_parameters;
5202 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5203 adev->device.open_output_stream = adev_open_output_stream;
5204 adev->device.close_output_stream = adev_close_output_stream;
5205 adev->device.open_input_stream = adev_open_input_stream;
5206 adev->device.close_input_stream = adev_close_input_stream;
5207 adev->device.dump = adev_dump;
5208
5209 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005210 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005211 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005212 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005215 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005216 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005217 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005218 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005219 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005220 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005221 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005222 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305223 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305224 adev->perf_lock_opts[0] = 0x101;
5225 adev->perf_lock_opts[1] = 0x20E;
5226 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305227
5228 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5229 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005231 adev->platform = platform_init(adev);
5232 if (!adev->platform) {
5233 free(adev->snd_dev_ref_cnt);
5234 free(adev);
5235 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5236 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005237 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305238 pthread_mutex_destroy(&adev->lock);
5239 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005240 return -EINVAL;
5241 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005242
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305243 if (audio_extn_qaf_is_enabled()) {
5244 ret = audio_extn_qaf_init(adev);
5245 if (ret < 0) {
5246 free(adev);
5247 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5248 *device = NULL;
5249 pthread_mutex_unlock(&adev_init_lock);
5250 pthread_mutex_destroy(&adev->lock);
5251 return ret;
5252 }
5253
5254 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5255 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5256 }
5257
Naresh Tanniru4c630392014-05-12 01:05:52 +05305258 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5259
Eric Laurentc4aef752013-09-12 17:45:53 -07005260 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5261 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5262 if (adev->visualizer_lib == NULL) {
5263 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5264 } else {
5265 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5266 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005267 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005268 "visualizer_hal_start_output");
5269 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005270 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005271 "visualizer_hal_stop_output");
5272 }
5273 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305274 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005275 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005276 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005277 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005278
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005279 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5280 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5281 if (adev->offload_effects_lib == NULL) {
5282 ALOGE("%s: DLOPEN failed for %s", __func__,
5283 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5284 } else {
5285 ALOGV("%s: DLOPEN successful for %s", __func__,
5286 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5287 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305288 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005289 "offload_effects_bundle_hal_start_output");
5290 adev->offload_effects_stop_output =
5291 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5292 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005293 adev->offload_effects_set_hpx_state =
5294 (int (*)(bool))dlsym(adev->offload_effects_lib,
5295 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305296 adev->offload_effects_get_parameters =
5297 (void (*)(struct str_parms *, struct str_parms *))
5298 dlsym(adev->offload_effects_lib,
5299 "offload_effects_bundle_get_parameters");
5300 adev->offload_effects_set_parameters =
5301 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5302 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005303 }
5304 }
5305
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005306 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5307 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5308 if (adev->adm_lib == NULL) {
5309 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5310 } else {
5311 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5312 adev->adm_init = (adm_init_t)
5313 dlsym(adev->adm_lib, "adm_init");
5314 adev->adm_deinit = (adm_deinit_t)
5315 dlsym(adev->adm_lib, "adm_deinit");
5316 adev->adm_register_input_stream = (adm_register_input_stream_t)
5317 dlsym(adev->adm_lib, "adm_register_input_stream");
5318 adev->adm_register_output_stream = (adm_register_output_stream_t)
5319 dlsym(adev->adm_lib, "adm_register_output_stream");
5320 adev->adm_deregister_stream = (adm_deregister_stream_t)
5321 dlsym(adev->adm_lib, "adm_deregister_stream");
5322 adev->adm_request_focus = (adm_request_focus_t)
5323 dlsym(adev->adm_lib, "adm_request_focus");
5324 adev->adm_abandon_focus = (adm_abandon_focus_t)
5325 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005326 adev->adm_set_config = (adm_set_config_t)
5327 dlsym(adev->adm_lib, "adm_set_config");
5328 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5329 dlsym(adev->adm_lib, "adm_request_focus_v2");
5330 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5331 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5332 adev->adm_on_routing_change = (adm_on_routing_change_t)
5333 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005334 }
5335 }
5336
Mingming Yin514a8bc2014-07-29 15:22:21 -07005337 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005338 //initialize this to false for now,
5339 //this will be set to true through set param
5340 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005341
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005342 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005343 *device = &adev->device.common;
5344
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305345 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5346 &adev->streams_output_cfg_list,
5347 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005348
Kiran Kandi910e1862013-10-29 13:29:42 -07005349 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005350
5351 char value[PROPERTY_VALUE_MAX];
5352 int trial;
5353 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5354 trial = atoi(value);
5355 if (period_size_is_plausible_for_low_latency(trial)) {
5356 pcm_config_low_latency.period_size = trial;
5357 pcm_config_low_latency.start_threshold = trial / 4;
5358 pcm_config_low_latency.avail_min = trial / 4;
5359 configured_low_latency_capture_period_size = trial;
5360 }
5361 }
5362 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5363 trial = atoi(value);
5364 if (period_size_is_plausible_for_low_latency(trial)) {
5365 configured_low_latency_capture_period_size = trial;
5366 }
5367 }
5368
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005369 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5370 af_period_multiplier = atoi(value);
5371 if (af_period_multiplier < 0)
5372 af_period_multiplier = 2;
5373 else if (af_period_multiplier > 4)
5374 af_period_multiplier = 4;
5375
5376 ALOGV("new period_multiplier = %d", af_period_multiplier);
5377 }
5378
vivek mehta446c3962015-09-14 10:57:35 -07005379 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005380 pthread_mutex_unlock(&adev_init_lock);
5381
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005382 if (adev->adm_init)
5383 adev->adm_data = adev->adm_init();
5384
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305385 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305386 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005387 audio_extn_adsp_hdlr_init(adev->mixer);
Eric Laurent994a6932013-07-17 11:51:42 -07005388 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005389 return 0;
5390}
5391
5392static struct hw_module_methods_t hal_module_methods = {
5393 .open = adev_open,
5394};
5395
5396struct audio_module HAL_MODULE_INFO_SYM = {
5397 .common = {
5398 .tag = HARDWARE_MODULE_TAG,
5399 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5400 .hal_api_version = HARDWARE_HAL_API_VERSION,
5401 .id = AUDIO_HARDWARE_MODULE_ID,
5402 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005403 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005404 .methods = &hal_module_methods,
5405 },
5406};