blob: 0b4ba95e71fc2f5ea762c69af48c1239f4c5c761 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053079#ifdef DYNAMIC_LOG_ENABLED
80#include <log_xml_parser.h>
81#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
82#include <log_utils.h>
83#endif
84
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070085#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053086/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
87#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053089#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070090
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070091#define PROXY_OPEN_RETRY_COUNT 100
92#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080093
Mingming Yin08c7e312015-03-16 18:10:58 -070094#ifdef USE_LL_AS_PRIMARY_OUTPUT
95#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
96#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
97#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080098#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070099#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
100#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800101
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700102#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
103
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700104static unsigned int configured_low_latency_capture_period_size =
105 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
106
Eric Laurentb23d5282013-05-14 15:27:20 -0700107struct pcm_config pcm_config_deep_buffer = {
108 .channels = 2,
109 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
110 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
111 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
114 .stop_threshold = INT_MAX,
115 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
116};
117
118struct pcm_config pcm_config_low_latency = {
119 .channels = 2,
120 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
121 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
122 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
123 .format = PCM_FORMAT_S16_LE,
124 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
125 .stop_threshold = INT_MAX,
126 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
127};
128
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129static int af_period_multiplier = 4;
130struct pcm_config pcm_config_rt = {
131 .channels = 2,
132 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
133 .period_size = ULL_PERIOD_SIZE, //1 ms
134 .period_count = 512, //=> buffer size is 512ms
135 .format = PCM_FORMAT_S16_LE,
136 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
137 .stop_threshold = INT_MAX,
138 .silence_threshold = 0,
139 .silence_size = 0,
140 .avail_min = ULL_PERIOD_SIZE, //1 ms
141};
142
Eric Laurentb23d5282013-05-14 15:27:20 -0700143struct pcm_config pcm_config_hdmi_multi = {
144 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
146 .period_size = HDMI_MULTI_PERIOD_SIZE,
147 .period_count = HDMI_MULTI_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = 0,
150 .stop_threshold = INT_MAX,
151 .avail_min = 0,
152};
153
154struct pcm_config pcm_config_audio_capture = {
155 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700156 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
157 .format = PCM_FORMAT_S16_LE,
158};
159
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700160struct pcm_config pcm_config_audio_capture_rt = {
161 .channels = 2,
162 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
163 .period_size = ULL_PERIOD_SIZE,
164 .period_count = 512,
165 .format = PCM_FORMAT_S16_LE,
166 .start_threshold = 0,
167 .stop_threshold = INT_MAX,
168 .silence_threshold = 0,
169 .silence_size = 0,
170 .avail_min = ULL_PERIOD_SIZE, //1 ms
171};
172
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700173#define AFE_PROXY_CHANNEL_COUNT 2
174#define AFE_PROXY_SAMPLING_RATE 48000
175
176#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
177#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
178
179struct pcm_config pcm_config_afe_proxy_playback = {
180 .channels = AFE_PROXY_CHANNEL_COUNT,
181 .rate = AFE_PROXY_SAMPLING_RATE,
182 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
183 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
186 .stop_threshold = INT_MAX,
187 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
188};
189
190#define AFE_PROXY_RECORD_PERIOD_SIZE 768
191#define AFE_PROXY_RECORD_PERIOD_COUNT 4
192
193struct pcm_config pcm_config_afe_proxy_record = {
194 .channels = AFE_PROXY_CHANNEL_COUNT,
195 .rate = AFE_PROXY_SAMPLING_RATE,
196 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
197 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
198 .format = PCM_FORMAT_S16_LE,
199 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
200 .stop_threshold = INT_MAX,
201 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
202};
203
Ashish Jainf1eaa582016-05-23 20:54:24 +0530204#define AUDIO_MAX_PCM_FORMATS 7
205
206const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
207 [AUDIO_FORMAT_DEFAULT] = 0,
208 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
209 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
210 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
211 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
212 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
213 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
214};
215
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800216const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700217 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
218 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700219 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
220 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700221 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700222 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700223 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
225 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
226 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
227 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
228 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
229 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
230 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700231
Eric Laurentb23d5282013-05-14 15:27:20 -0700232 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700233 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530234 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
235 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
236 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700237 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700238 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700239 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800240 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800241 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700242 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700243
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700244 [USECASE_VOICE2_CALL] = "voice2-call",
245 [USECASE_VOLTE_CALL] = "volte-call",
246 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800247 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800248 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
249 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800250 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700251 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
252 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
253 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800254 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
255 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
256 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
257
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700258 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
259 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700260 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
261 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700262
263 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
264 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700265 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700266};
267
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700268static const audio_usecase_t offload_usecases[] = {
269 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700270 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
272 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
274 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
275 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
276 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
277 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700278};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800279
280#define STRING_TO_ENUM(string) { #string, string }
281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800282struct string_to_enum {
283 const char *name;
284 uint32_t value;
285};
286
287static const struct string_to_enum out_channels_name_to_enum_table[] = {
288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700292 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800293 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
294 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
296};
297
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700298static const struct string_to_enum out_formats_name_to_enum_table[] = {
299 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
300 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
301 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700302 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800303 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
304 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
305};
306
307//list of all supported sample rates by HDMI specification.
308static const int out_hdmi_sample_rates[] = {
309 32000, 44100, 48000, 88200, 96000, 176400, 192000,
310};
311
312static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
313 STRING_TO_ENUM(32000),
314 STRING_TO_ENUM(44100),
315 STRING_TO_ENUM(48000),
316 STRING_TO_ENUM(88200),
317 STRING_TO_ENUM(96000),
318 STRING_TO_ENUM(176400),
319 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700320};
321
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700322static struct audio_device *adev = NULL;
323static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700324static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700325//cache last MBDRC cal step level
326static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700327
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700328static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
329 int flags __unused)
330{
331 int dir = 0;
332 switch (uc_id) {
333 case USECASE_AUDIO_RECORD_LOW_LATENCY:
334 dir = 1;
335 case USECASE_AUDIO_PLAYBACK_ULL:
336 break;
337 default:
338 return false;
339 }
340
341 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
342 PCM_PLAYBACK : PCM_CAPTURE);
343 if (adev->adm_is_noirq_avail)
344 return adev->adm_is_noirq_avail(adev->adm_data,
345 adev->snd_card, dev_id, dir);
346 return false;
347}
348
349static void register_out_stream(struct stream_out *out)
350{
351 struct audio_device *adev = out->dev;
352 if (is_offload_usecase(out->usecase) ||
353 !adev->adm_register_output_stream)
354 return;
355
356 // register stream first for backward compatibility
357 adev->adm_register_output_stream(adev->adm_data,
358 out->handle,
359 out->flags);
360
361 if (!adev->adm_set_config)
362 return;
363
364 if (out->realtime)
365 adev->adm_set_config(adev->adm_data,
366 out->handle,
367 out->pcm, &out->config);
368}
369
370static void register_in_stream(struct stream_in *in)
371{
372 struct audio_device *adev = in->dev;
373 if (!adev->adm_register_input_stream)
374 return;
375
376 adev->adm_register_input_stream(adev->adm_data,
377 in->capture_handle,
378 in->flags);
379
380 if (!adev->adm_set_config)
381 return;
382
383 if (in->realtime)
384 adev->adm_set_config(adev->adm_data,
385 in->capture_handle,
386 in->pcm,
387 &in->config);
388}
389
390static void request_out_focus(struct stream_out *out, long ns)
391{
392 struct audio_device *adev = out->dev;
393
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700394 if (adev->adm_request_focus_v2)
395 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
396 else if (adev->adm_request_focus)
397 adev->adm_request_focus(adev->adm_data, out->handle);
398}
399
400static void request_in_focus(struct stream_in *in, long ns)
401{
402 struct audio_device *adev = in->dev;
403
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700404 if (adev->adm_request_focus_v2)
405 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
406 else if (adev->adm_request_focus)
407 adev->adm_request_focus(adev->adm_data, in->capture_handle);
408}
409
410static void release_out_focus(struct stream_out *out)
411{
412 struct audio_device *adev = out->dev;
413
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, out->handle);
416}
417
418static void release_in_focus(struct stream_in *in)
419{
420 struct audio_device *adev = in->dev;
421 if (adev->adm_abandon_focus)
422 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
423}
424
vivek mehtaa76401a2015-04-24 14:12:15 -0700425__attribute__ ((visibility ("default")))
426bool audio_hw_send_gain_dep_calibration(int level) {
427 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700428 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700429
430 pthread_mutex_lock(&adev_init_lock);
431
432 if (adev != NULL && adev->platform != NULL) {
433 pthread_mutex_lock(&adev->lock);
434 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700435
436 // if cal set fails, cache level info
437 // if cal set succeds, reset known last cal set
438 if (!ret_val)
439 last_known_cal_step = level;
440 else if (last_known_cal_step != -1)
441 last_known_cal_step = -1;
442
vivek mehtaa76401a2015-04-24 14:12:15 -0700443 pthread_mutex_unlock(&adev->lock);
444 } else {
445 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
446 }
447
448 pthread_mutex_unlock(&adev_init_lock);
449
450 return ret_val;
451}
452
Ashish Jain5106d362016-05-11 19:23:33 +0530453static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
454{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800455 bool gapless_enabled = false;
456 const char *mixer_ctl_name = "Compress Gapless Playback";
457 struct mixer_ctl *ctl;
458
459 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530460 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
461
462 /*Disable gapless if its AV playback*/
463 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800464
465 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
466 if (!ctl) {
467 ALOGE("%s: Could not get ctl for mixer cmd - %s",
468 __func__, mixer_ctl_name);
469 return -EINVAL;
470 }
471
472 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
473 ALOGE("%s: Could not set gapless mode %d",
474 __func__, gapless_enabled);
475 return -EINVAL;
476 }
477 return 0;
478}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700479
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700480__attribute__ ((visibility ("default")))
481int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
482 int table_size) {
483 int ret_val = 0;
484 ALOGV("%s: enter ... ", __func__);
485
486 pthread_mutex_lock(&adev_init_lock);
487 if (adev == NULL) {
488 ALOGW("%s: adev is NULL .... ", __func__);
489 goto done;
490 }
491
492 pthread_mutex_lock(&adev->lock);
493 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
494 pthread_mutex_unlock(&adev->lock);
495done:
496 pthread_mutex_unlock(&adev_init_lock);
497 ALOGV("%s: exit ... ", __func__);
498 return ret_val;
499}
500
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700501static bool is_supported_format(audio_format_t format)
502{
Eric Laurent86e17132013-09-12 17:49:30 -0700503 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530504 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530505 format == AUDIO_FORMAT_AAC_LC ||
506 format == AUDIO_FORMAT_AAC_HE_V1 ||
507 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530508 format == AUDIO_FORMAT_AAC_ADTS_LC ||
509 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
510 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530511 format == AUDIO_FORMAT_AAC_LATM_LC ||
512 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
513 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530514 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
515 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530516 format == AUDIO_FORMAT_PCM_FLOAT ||
517 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700518 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530519 format == AUDIO_FORMAT_AC3 ||
520 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700521 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530522 format == AUDIO_FORMAT_DTS ||
523 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800524 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530525 format == AUDIO_FORMAT_ALAC ||
526 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530527 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530528 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800529 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530530 format == AUDIO_FORMAT_WMA_PRO ||
531 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800532 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700533
534 return false;
535}
536
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700537static inline bool is_mmap_usecase(audio_usecase_t uc_id)
538{
539 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
540 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
541}
542
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530543int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530544{
545 int snd_scard_state;
546
547 if (!adev)
548 return SND_CARD_STATE_OFFLINE;
549
550 pthread_mutex_lock(&adev->snd_card_status.lock);
551 snd_scard_state = adev->snd_card_status.state;
552 pthread_mutex_unlock(&adev->snd_card_status.lock);
553
554 return snd_scard_state;
555}
556
557static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
558{
559 if (!adev)
560 return -ENOSYS;
561
562 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700563 if (adev->snd_card_status.state != snd_scard_state) {
564 adev->snd_card_status.state = snd_scard_state;
565 platform_snd_card_update(adev->platform, snd_scard_state);
566 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530567 pthread_mutex_unlock(&adev->snd_card_status.lock);
568
569 return 0;
570}
571
Avinash Vaish71a8b972014-07-24 15:36:33 +0530572static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
573 struct audio_usecase *uc_info)
574{
575 struct listnode *node;
576 struct audio_usecase *usecase;
577
578 if (uc_info == NULL)
579 return -EINVAL;
580
581 /* Re-route all voice usecases on the shared backend other than the
582 specified usecase to new snd devices */
583 list_for_each(node, &adev->usecase_list) {
584 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800585 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530586 enable_audio_route(adev, usecase);
587 }
588 return 0;
589}
590
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530591static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530592{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530593 ALOGV("%s", __func__);
594 audio_route_apply_and_update_path(adev->audio_route,
595 "asrc-mode");
596 adev->asrc_mode_enabled = true;
597}
598
599static void disable_asrc_mode(struct audio_device *adev)
600{
601 ALOGV("%s", __func__);
602 audio_route_reset_and_update_path(adev->audio_route,
603 "asrc-mode");
604 adev->asrc_mode_enabled = false;
605}
606
607/*
608 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
609 * 44.1 or Native DSD backends are enabled for any of current use case.
610 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
611 * - Disable current mix path use case(Headphone backend) and re-enable it with
612 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
613 * e.g. Naitve DSD or Headphone 44.1 -> + 48
614 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530615static void check_and_set_asrc_mode(struct audio_device *adev,
616 struct audio_usecase *uc_info,
617 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530618{
619 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530620 int i, num_new_devices = 0;
621 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
622 /*
623 *Split snd device for new combo use case
624 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
625 */
626 if (platform_split_snd_device(adev->platform,
627 snd_device,
628 &num_new_devices,
629 split_new_snd_devices) == 0) {
630 for (i = 0; i < num_new_devices; i++)
631 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
632 } else {
633 int new_backend_idx = platform_get_backend_index(snd_device);
634 if (((new_backend_idx == HEADPHONE_BACKEND) ||
635 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
636 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
637 !adev->asrc_mode_enabled) {
638 struct listnode *node = NULL;
639 struct audio_usecase *uc = NULL;
640 struct stream_out *curr_out = NULL;
641 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
642 int i, num_devices, ret = 0;
643 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530644
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530645 list_for_each(node, &adev->usecase_list) {
646 uc = node_to_item(node, struct audio_usecase, list);
647 curr_out = (struct stream_out*) uc->stream.out;
648 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
649 /*
650 *Split snd device for existing combo use case
651 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
652 */
653 ret = platform_split_snd_device(adev->platform,
654 uc->out_snd_device,
655 &num_devices,
656 split_snd_devices);
657 if (ret < 0 || num_devices == 0) {
658 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
659 split_snd_devices[0] = uc->out_snd_device;
660 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800661 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530662 for (i = 0; i < num_devices; i++) {
663 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
664 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
665 if((new_backend_idx == HEADPHONE_BACKEND) &&
666 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
667 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
668 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
669 __func__);
670 enable_asrc_mode(adev);
671 break;
672 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
673 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
674 (usecase_backend_idx == HEADPHONE_BACKEND)) {
675 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
676 __func__);
677 disable_audio_route(adev, uc);
678 disable_snd_device(adev, uc->out_snd_device);
679 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
680 if (new_backend_idx == DSD_NATIVE_BACKEND)
681 audio_route_apply_and_update_path(adev->audio_route,
682 "hph-true-highquality-mode");
683 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
684 (curr_out->bit_width >= 24))
685 audio_route_apply_and_update_path(adev->audio_route,
686 "hph-highquality-mode");
687 enable_asrc_mode(adev);
688 enable_snd_device(adev, uc->out_snd_device);
689 enable_audio_route(adev, uc);
690 break;
691 }
692 }
693 // reset split devices count
694 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800695 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530696 if (adev->asrc_mode_enabled)
697 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530698 }
699 }
700 }
701}
702
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700703int pcm_ioctl(struct pcm *pcm, int request, ...)
704{
705 va_list ap;
706 void * arg;
707 int pcm_fd = *(int*)pcm;
708
709 va_start(ap, request);
710 arg = va_arg(ap, void *);
711 va_end(ap);
712
713 return ioctl(pcm_fd, request, arg);
714}
715
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700716int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700717 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800718{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700720 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530721 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800722
723 if (usecase == NULL)
724 return -EINVAL;
725
726 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
727
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800728 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800730 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700731 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800732
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800733#ifdef DS1_DOLBY_DAP_ENABLED
734 audio_extn_dolby_set_dmid(adev);
735 audio_extn_dolby_set_endpoint(adev);
736#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700737 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700738 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530739 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700740 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530741 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530742 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
743 out = usecase->stream.out;
744 if (out && out->compr)
745 audio_extn_utils_compress_set_clk_rec_mode(usecase);
746 }
747
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800748 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700749 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700750 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700751 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800752 ALOGV("%s: exit", __func__);
753 return 0;
754}
755
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700756int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700757 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800758{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700760 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800761
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530762 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800763 return -EINVAL;
764
765 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700766 if (usecase->type == PCM_CAPTURE)
767 snd_device = usecase->in_snd_device;
768 else
769 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800770 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700771 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700772 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700773 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700774 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530775 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800776 ALOGV("%s: exit", __func__);
777 return 0;
778}
779
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700780int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700781 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800782{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530783 int i, num_devices = 0;
784 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700785 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
786
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800787 if (snd_device < SND_DEVICE_MIN ||
788 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800789 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800790 return -EINVAL;
791 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792
793 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700794
795 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
796 ALOGE("%s: Invalid sound device returned", __func__);
797 return -EINVAL;
798 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700799 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700800 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700801 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802 return 0;
803 }
804
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530805
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700806 if (audio_extn_spkr_prot_is_enabled())
807 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700808
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800809 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
810 audio_extn_spkr_prot_is_enabled()) {
811 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700812 adev->snd_dev_ref_cnt[snd_device]--;
813 return -EINVAL;
814 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200815 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800816 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800817 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200818 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800819 return -EINVAL;
820 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700821 } else if (platform_split_snd_device(adev->platform,
822 snd_device,
823 &num_devices,
824 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530825 for (i = 0; i < num_devices; i++) {
826 enable_snd_device(adev, new_snd_devices[i]);
827 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800828 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700829 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530830
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530831
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530832 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
833 (audio_extn_a2dp_start_playback() < 0)) {
834 ALOGE(" fail to configure A2dp control path ");
835 return -EINVAL;
836 }
837
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700838 /* due to the possibility of calibration overwrite between listen
839 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700840 audio_extn_sound_trigger_update_device_status(snd_device,
841 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530842 audio_extn_listen_update_device_status(snd_device,
843 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700844 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700845 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700846 audio_extn_sound_trigger_update_device_status(snd_device,
847 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530848 audio_extn_listen_update_device_status(snd_device,
849 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700850 return -EINVAL;
851 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300852 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700853 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530854
855 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
856 !adev->native_playback_enabled &&
857 audio_is_true_native_stream_active(adev)) {
858 ALOGD("%s: %d: napb: enabling native mode in hardware",
859 __func__, __LINE__);
860 audio_route_apply_and_update_path(adev->audio_route,
861 "true-native-mode");
862 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800865 return 0;
866}
867
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700868int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700869 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800870{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530871 int i, num_devices = 0;
872 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700873 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
874
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800875 if (snd_device < SND_DEVICE_MIN ||
876 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800877 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800878 return -EINVAL;
879 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
881 ALOGE("%s: device ref cnt is already 0", __func__);
882 return -EINVAL;
883 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700884
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700886
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700887 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
888 ALOGE("%s: Invalid sound device returned", __func__);
889 return -EINVAL;
890 }
891
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700893 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530894
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800895 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
896 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700897 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700898 } else if (platform_split_snd_device(adev->platform,
899 snd_device,
900 &num_devices,
901 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530902 for (i = 0; i < num_devices; i++) {
903 disable_snd_device(adev, new_snd_devices[i]);
904 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300905 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700906 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300907 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700908
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530909 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
910 audio_extn_a2dp_stop_playback();
911
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700912 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530913 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530914 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
915 adev->native_playback_enabled) {
916 ALOGD("%s: %d: napb: disabling native mode in hardware",
917 __func__, __LINE__);
918 audio_route_reset_and_update_path(adev->audio_route,
919 "true-native-mode");
920 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530921 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
922 adev->asrc_mode_enabled) {
923 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530924 disable_asrc_mode(adev);
925 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530926 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530927
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200928 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700929 audio_extn_sound_trigger_update_device_status(snd_device,
930 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530931 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800932 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935 return 0;
936}
937
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700938/*
939 legend:
940 uc - existing usecase
941 new_uc - new usecase
942 d1, d11, d2 - SND_DEVICE enums
943 a1, a2 - corresponding ANDROID device enums
944 B1, B2 - backend strings
945
946case 1
947 uc->dev d1 (a1) B1
948 new_uc->dev d1 (a1), d2 (a2) B1, B2
949
950 resolution: disable and enable uc->dev on d1
951
952case 2
953 uc->dev d1 (a1) B1
954 new_uc->dev d11 (a1) B1
955
956 resolution: need to switch uc since d1 and d11 are related
957 (e.g. speaker and voice-speaker)
958 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
959
960case 3
961 uc->dev d1 (a1) B1
962 new_uc->dev d2 (a2) B2
963
964 resolution: no need to switch uc
965
966case 4
967 uc->dev d1 (a1) B1
968 new_uc->dev d2 (a2) B1
969
970 resolution: disable enable uc-dev on d2 since backends match
971 we cannot enable two streams on two different devices if they
972 share the same backend. e.g. if offload is on speaker device using
973 QUAD_MI2S backend and a low-latency stream is started on voice-handset
974 using the same backend, offload must also be switched to voice-handset.
975
976case 5
977 uc->dev d1 (a1) B1
978 new_uc->dev d1 (a1), d2 (a2) B1
979
980 resolution: disable enable uc-dev on d2 since backends match
981 we cannot enable two streams on two different devices if they
982 share the same backend.
983
984case 6
985 uc->dev d1 (a1) B1
986 new_uc->dev d2 (a1) B2
987
988 resolution: no need to switch
989
990case 7
991 uc->dev d1 (a1), d2 (a2) B1, B2
992 new_uc->dev d1 (a1) B1
993
994 resolution: no need to switch
995
996*/
997static snd_device_t derive_playback_snd_device(void * platform,
998 struct audio_usecase *uc,
999 struct audio_usecase *new_uc,
1000 snd_device_t new_snd_device)
1001{
1002 audio_devices_t a1 = uc->stream.out->devices;
1003 audio_devices_t a2 = new_uc->stream.out->devices;
1004
1005 snd_device_t d1 = uc->out_snd_device;
1006 snd_device_t d2 = new_snd_device;
1007
1008 // Treat as a special case when a1 and a2 are not disjoint
1009 if ((a1 != a2) && (a1 & a2)) {
1010 snd_device_t d3[2];
1011 int num_devices = 0;
1012 int ret = platform_split_snd_device(platform,
1013 popcount(a1) > 1 ? d1 : d2,
1014 &num_devices,
1015 d3);
1016 if (ret < 0) {
1017 if (ret != -ENOSYS) {
1018 ALOGW("%s failed to split snd_device %d",
1019 __func__,
1020 popcount(a1) > 1 ? d1 : d2);
1021 }
1022 goto end;
1023 }
1024
1025 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1026 // But if it does happen, we need to give priority to d2 if
1027 // the combo devices active on the existing usecase share a backend.
1028 // This is because we cannot have a usecase active on a combo device
1029 // and a new usecase requests one device in this combo pair.
1030 if (platform_check_backends_match(d3[0], d3[1])) {
1031 return d2; // case 5
1032 } else {
1033 return d1; // case 1
1034 }
1035 } else {
1036 if (platform_check_backends_match(d1, d2)) {
1037 return d2; // case 2, 4
1038 } else {
1039 return d1; // case 6, 3
1040 }
1041 }
1042
1043end:
1044 return d2; // return whatever was calculated before.
1045}
1046
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001047static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301048 struct audio_usecase *uc_info,
1049 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050{
1051 struct listnode *node;
1052 struct audio_usecase *usecase;
1053 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301054 snd_device_t uc_derive_snd_device;
1055 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001056 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001057 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301058 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001059 /*
1060 * This function is to make sure that all the usecases that are active on
1061 * the hardware codec backend are always routed to any one device that is
1062 * handled by the hardware codec.
1063 * For example, if low-latency and deep-buffer usecases are currently active
1064 * on speaker and out_set_parameters(headset) is received on low-latency
1065 * output, then we have to make sure deep-buffer is also switched to headset,
1066 * because of the limitation that both the devices cannot be enabled
1067 * at the same time as they share the same backend.
1068 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001069 /*
1070 * This call is to check if we need to force routing for a particular stream
1071 * If there is a backend configuration change for the device when a
1072 * new stream starts, then ADM needs to be closed and re-opened with the new
1073 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001074 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001075 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001076 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1077 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301078 /* For a2dp device reconfigure all active sessions
1079 * with new AFE encoder format based on a2dp state
1080 */
1081 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1082 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1083 audio_extn_a2dp_is_force_device_switch()) {
1084 force_routing = true;
1085 force_restart_session = true;
1086 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301087 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1088
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001089 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001090 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001091 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001092 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1093 switch_device[i] = false;
1094
1095 list_for_each(node, &adev->usecase_list) {
1096 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001097
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301098 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1099 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301100 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301101 platform_get_snd_device_name(usecase->out_snd_device),
1102 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301103 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1104 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1105 usecase, uc_info, snd_device);
1106 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1107 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1108 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1109 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1110 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1111 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1112 ((force_restart_session) ||
1113 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301114 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1115 __func__, use_case_table[usecase->id],
1116 platform_get_snd_device_name(usecase->out_snd_device));
1117 disable_audio_route(adev, usecase);
1118 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301119 /* Enable existing usecase on derived playback device */
1120 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301121 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301122 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 }
1124 }
1125
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301126 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1127 num_uc_to_switch);
1128
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001129 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001130 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301132 /* Make sure the previous devices to be disabled first and then enable the
1133 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 list_for_each(node, &adev->usecase_list) {
1135 usecase = node_to_item(node, struct audio_usecase, list);
1136 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001137 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 }
1139 }
1140
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001141 list_for_each(node, &adev->usecase_list) {
1142 usecase = node_to_item(node, struct audio_usecase, list);
1143 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301144 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001145 }
1146 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148 /* Re-route all the usecases on the shared backend other than the
1149 specified usecase to new snd devices */
1150 list_for_each(node, &adev->usecase_list) {
1151 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301152 /* Update the out_snd_device only before enabling the audio route */
1153 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301154 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301155 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301156 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301157 use_case_table[usecase->id],
1158 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001159 /* Update voc calibration before enabling VoIP route */
1160 if (usecase->type == VOIP_CALL)
1161 status = platform_switch_voice_call_device_post(adev->platform,
1162 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001163 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301164 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301165 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 }
1167 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 }
1169}
1170
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301171static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001172 struct audio_usecase *uc_info,
1173 snd_device_t snd_device)
1174{
1175 struct listnode *node;
1176 struct audio_usecase *usecase;
1177 bool switch_device[AUDIO_USECASE_MAX];
1178 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301179 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001180 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301182 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1183 snd_device);
1184 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301185
1186 /*
1187 * Make sure out devices is checked against out codec backend device and
1188 * also in devices against in codec backend. Checking out device against in
1189 * codec backend or vice versa causes issues.
1190 */
1191 if (uc_info->type == PCM_CAPTURE)
1192 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001193 /*
1194 * This function is to make sure that all the active capture usecases
1195 * are always routed to the same input sound device.
1196 * For example, if audio-record and voice-call usecases are currently
1197 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1198 * is received for voice call then we have to make sure that audio-record
1199 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1200 * because of the limitation that two devices cannot be enabled
1201 * at the same time if they share the same backend.
1202 */
1203 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1204 switch_device[i] = false;
1205
1206 list_for_each(node, &adev->usecase_list) {
1207 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301208 /*
1209 * TODO: Enhance below condition to handle BT sco/USB multi recording
1210 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001211 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001212 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301213 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301214 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301215 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301216 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001217 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001218 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1219 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001220 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001221 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001222 switch_device[usecase->id] = true;
1223 num_uc_to_switch++;
1224 }
1225 }
1226
1227 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001228 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001229
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301230 /* Make sure the previous devices to be disabled first and then enable the
1231 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001235 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001236 }
1237 }
1238
1239 list_for_each(node, &adev->usecase_list) {
1240 usecase = node_to_item(node, struct audio_usecase, list);
1241 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001242 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001243 }
1244 }
1245
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001246 /* Re-route all the usecases on the shared backend other than the
1247 specified usecase to new snd devices */
1248 list_for_each(node, &adev->usecase_list) {
1249 usecase = node_to_item(node, struct audio_usecase, list);
1250 /* Update the in_snd_device only before enabling the audio route */
1251 if (switch_device[usecase->id] ) {
1252 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001253 if (usecase->type != VOICE_CALL) {
1254 /* Update voc calibration before enabling VoIP route */
1255 if (usecase->type == VOIP_CALL)
1256 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001257 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001258 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301259 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001260 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001261 }
1262 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001263 }
1264}
1265
Mingming Yin3a941d42016-02-17 18:08:05 -08001266static void reset_hdmi_sink_caps(struct stream_out *out) {
1267 int i = 0;
1268
1269 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1270 out->supported_channel_masks[i] = 0;
1271 }
1272 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1273 out->supported_formats[i] = 0;
1274 }
1275 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1276 out->supported_sample_rates[i] = 0;
1277 }
1278}
1279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001280/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001281static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282{
Mingming Yin3a941d42016-02-17 18:08:05 -08001283 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001284 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285
Mingming Yin3a941d42016-02-17 18:08:05 -08001286 reset_hdmi_sink_caps(out);
1287
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001288 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001289 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001290 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001291 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001292 }
1293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001295 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001296 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001297 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001298 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1299 case 6:
1300 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1301 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1302 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1303 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1304 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1305 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001306 break;
1307 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001308 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001309 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 break;
1311 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001312
1313 // check channel format caps
1314 i = 0;
1315 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1316 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1317 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1318 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1319 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1320 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1321 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1322 }
1323
Ben Romberger1aaaf862017-04-06 17:49:46 -07001324 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1325 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1326 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1327 }
1328
Mingming Yin3a941d42016-02-17 18:08:05 -08001329 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1330 ALOGV(":%s HDMI supports DTS format", __func__);
1331 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1332 }
1333
1334 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1335 ALOGV(":%s HDMI supports DTS HD format", __func__);
1336 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1337 }
1338
1339
1340 // check sample rate caps
1341 i = 0;
1342 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1343 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1344 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1345 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1346 }
1347 }
1348
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001349 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350}
1351
Alexy Josephb1379942016-01-29 15:49:38 -08001352audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001353 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001354{
1355 struct audio_usecase *usecase;
1356 struct listnode *node;
1357
1358 list_for_each(node, &adev->usecase_list) {
1359 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001360 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001361 ALOGV("%s: usecase id %d", __func__, usecase->id);
1362 return usecase->id;
1363 }
1364 }
1365 return USECASE_INVALID;
1366}
1367
Alexy Josephb1379942016-01-29 15:49:38 -08001368struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001369 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001370{
1371 struct audio_usecase *usecase;
1372 struct listnode *node;
1373
1374 list_for_each(node, &adev->usecase_list) {
1375 usecase = node_to_item(node, struct audio_usecase, list);
1376 if (usecase->id == uc_id)
1377 return usecase;
1378 }
1379 return NULL;
1380}
1381
Dhananjay Kumard4833242016-10-06 22:09:12 +05301382struct stream_in *get_next_active_input(const struct audio_device *adev)
1383{
1384 struct audio_usecase *usecase;
1385 struct listnode *node;
1386
1387 list_for_each_reverse(node, &adev->usecase_list) {
1388 usecase = node_to_item(node, struct audio_usecase, list);
1389 if (usecase->type == PCM_CAPTURE)
1390 return usecase->stream.in;
1391 }
1392 return NULL;
1393}
1394
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301395/*
1396 * is a true native playback active
1397 */
1398bool audio_is_true_native_stream_active(struct audio_device *adev)
1399{
1400 bool active = false;
1401 int i = 0;
1402 struct listnode *node;
1403
1404 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1405 ALOGV("%s:napb: not in true mode or non hdphones device",
1406 __func__);
1407 active = false;
1408 goto exit;
1409 }
1410
1411 list_for_each(node, &adev->usecase_list) {
1412 struct audio_usecase *uc;
1413 uc = node_to_item(node, struct audio_usecase, list);
1414 struct stream_out *curr_out =
1415 (struct stream_out*) uc->stream.out;
1416
1417 if (curr_out && PCM_PLAYBACK == uc->type) {
1418 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1419 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1420 uc->id, curr_out->sample_rate,
1421 curr_out->bit_width,
1422 platform_get_snd_device_name(uc->out_snd_device));
1423
1424 if (is_offload_usecase(uc->id) &&
1425 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1426 active = true;
1427 ALOGD("%s:napb:native stream detected", __func__);
1428 }
1429 }
1430 }
1431exit:
1432 return active;
1433}
1434
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301435/*
1436 * if native DSD playback active
1437 */
1438bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1439{
1440 bool active = false;
1441 struct listnode *node = NULL;
1442 struct audio_usecase *uc = NULL;
1443 struct stream_out *curr_out = NULL;
1444
1445 list_for_each(node, &adev->usecase_list) {
1446 uc = node_to_item(node, struct audio_usecase, list);
1447 curr_out = (struct stream_out*) uc->stream.out;
1448
1449 if (curr_out && PCM_PLAYBACK == uc->type &&
1450 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1451 active = true;
1452 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301453 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301454 }
1455 }
1456 return active;
1457}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301458
1459static bool force_device_switch(struct audio_usecase *usecase)
1460{
1461 bool ret = false;
1462 bool is_it_true_mode = false;
1463
1464 if (is_offload_usecase(usecase->id) &&
1465 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001466 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1467 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1468 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301469 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1470 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1471 (!is_it_true_mode && adev->native_playback_enabled)){
1472 ret = true;
1473 ALOGD("napb: time to toggle native mode");
1474 }
1475 }
1476
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301477 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301478 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1479 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301480 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001481 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301482 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301483 ALOGD("Force a2dp device switch to update new encoder config");
1484 ret = true;
1485 }
1486
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301487 return ret;
1488}
1489
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001490int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001492 snd_device_t out_snd_device = SND_DEVICE_NONE;
1493 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494 struct audio_usecase *usecase = NULL;
1495 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001496 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001497 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001498 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301501 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1502
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503 usecase = get_usecase_from_list(adev, uc_id);
1504 if (usecase == NULL) {
1505 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1506 return -EINVAL;
1507 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001509 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001510 (usecase->type == VOIP_CALL) ||
1511 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301512 if(usecase->stream.out == NULL) {
1513 ALOGE("%s: stream.out is NULL", __func__);
1514 return -EINVAL;
1515 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001516 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001517 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001518 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 usecase->devices = usecase->stream.out->devices;
1520 } else {
1521 /*
1522 * If the voice call is active, use the sound devices of voice call usecase
1523 * so that it would not result any device switch. All the usecases will
1524 * be switched to new device when select_devices() is called for voice call
1525 * usecase. This is to avoid switching devices for voice call when
1526 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001527 * choose voice call device only if the use case device is
1528 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001529 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001530 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001531 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001532 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001533 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1534 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301535 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1536 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001537 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 in_snd_device = vc_usecase->in_snd_device;
1539 out_snd_device = vc_usecase->out_snd_device;
1540 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001541 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001542 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001543 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001544 if ((voip_usecase != NULL) &&
1545 (usecase->type == PCM_PLAYBACK) &&
1546 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001547 out_snd_device_backend_match = platform_check_backends_match(
1548 voip_usecase->out_snd_device,
1549 platform_get_output_snd_device(
1550 adev->platform,
1551 usecase->stream.out));
1552 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001553 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001554 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1555 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001556 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001557 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001558 in_snd_device = voip_usecase->in_snd_device;
1559 out_snd_device = voip_usecase->out_snd_device;
1560 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001561 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001562 hfp_ucid = audio_extn_hfp_get_usecase();
1563 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001564 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001565 in_snd_device = hfp_usecase->in_snd_device;
1566 out_snd_device = hfp_usecase->out_snd_device;
1567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 }
1569 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301570 if (usecase->stream.out == NULL) {
1571 ALOGE("%s: stream.out is NULL", __func__);
1572 return -EINVAL;
1573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574 usecase->devices = usecase->stream.out->devices;
1575 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001576 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001577 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001578 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001579 if (usecase->stream.out == adev->primary_output &&
1580 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001581 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001582 select_devices(adev, adev->active_input->usecase);
1583 }
1584 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301586 if (usecase->stream.in == NULL) {
1587 ALOGE("%s: stream.in is NULL", __func__);
1588 return -EINVAL;
1589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 usecase->devices = usecase->stream.in->device;
1591 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001592 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001593 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001594 if (adev->active_input &&
1595 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301596 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1597 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1598 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001599 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001600 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001601 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1602 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001603 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001604 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001605 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001606 }
1607 }
1608
1609 if (out_snd_device == usecase->out_snd_device &&
1610 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301611
1612 if (!force_device_switch(usecase))
1613 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614 }
1615
sangwoobc677242013-08-08 16:53:43 +09001616 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001617 out_snd_device, platform_get_snd_device_name(out_snd_device),
1618 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620 /*
1621 * Limitation: While in call, to do a device switch we need to disable
1622 * and enable both RX and TX devices though one of them is same as current
1623 * device.
1624 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001625 if ((usecase->type == VOICE_CALL) &&
1626 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1627 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001628 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001629 }
1630
1631 if (((usecase->type == VOICE_CALL) ||
1632 (usecase->type == VOIP_CALL)) &&
1633 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1634 /* Disable sidetone only if voice/voip call already exists */
1635 if (voice_is_call_state_active(adev) ||
1636 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001637 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001638
1639 /* Disable aanc only if voice call exists */
1640 if (voice_is_call_state_active(adev))
1641 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001642 }
1643
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001644 /* Disable current sound devices */
1645 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001646 disable_audio_route(adev, usecase);
1647 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648 }
1649
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001650 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001651 disable_audio_route(adev, usecase);
1652 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 }
1654
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001655 /* Applicable only on the targets that has external modem.
1656 * New device information should be sent to modem before enabling
1657 * the devices to reduce in-call device switch time.
1658 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001659 if ((usecase->type == VOICE_CALL) &&
1660 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1661 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001662 status = platform_switch_voice_call_enable_device_config(adev->platform,
1663 out_snd_device,
1664 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001665 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001666
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667 /* Enable new sound devices */
1668 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001669 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301670 if (platform_check_codec_asrc_support(adev->platform))
1671 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001672 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673 }
1674
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001675 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301676 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001677 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001678 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001679
Avinash Vaish71a8b972014-07-24 15:36:33 +05301680 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001681 status = platform_switch_voice_call_device_post(adev->platform,
1682 out_snd_device,
1683 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301684 enable_audio_route_for_voice_usecases(adev, usecase);
1685 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001686
sangwoo170731f2013-06-08 15:36:36 +09001687 usecase->in_snd_device = in_snd_device;
1688 usecase->out_snd_device = out_snd_device;
1689
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301690 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1691 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301692 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001693 if ((24 == usecase->stream.out->bit_width) &&
1694 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1695 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1696 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1697 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1698 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1699 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1700 /*
1701 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1702 * configured device sample rate, if not update the COPP rate to be equal to the
1703 * device sample rate, else open COPP at stream sample rate
1704 */
1705 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1706 usecase->stream.out->sample_rate,
1707 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301708 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1709 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001710 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1711 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1712 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1713 }
1714
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001715 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001716 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001717 audio_extn_gef_notify_device_config(
1718 usecase->stream.out->devices,
1719 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001720 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001721 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001722 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301723 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001724 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001725
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001726 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001727 /* Enable aanc only if voice call exists */
1728 if (voice_is_call_state_active(adev))
1729 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1730
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001731 /* Enable sidetone only if other voice/voip call already exists */
1732 if (voice_is_call_state_active(adev) ||
1733 voice_extn_compress_voip_is_started(adev))
1734 voice_set_sidetone(adev, out_snd_device, true);
1735 }
1736
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001737 /* Applicable only on the targets that has external modem.
1738 * Enable device command should be sent to modem only after
1739 * enabling voice call mixer controls
1740 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001741 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001742 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1743 out_snd_device,
1744 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301745 ALOGD("%s: done",__func__);
1746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 return status;
1748}
1749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750static int stop_input_stream(struct stream_in *in)
1751{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301752 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 struct audio_usecase *uc_info;
1754 struct audio_device *adev = in->dev;
1755
Eric Laurent994a6932013-07-17 11:51:42 -07001756 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001757 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 uc_info = get_usecase_from_list(adev, in->usecase);
1759 if (uc_info == NULL) {
1760 ALOGE("%s: Could not find the usecase (%d) in the list",
1761 __func__, in->usecase);
1762 return -EINVAL;
1763 }
1764
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001765 /* Close in-call recording streams */
1766 voice_check_and_stop_incall_rec_usecase(adev, in);
1767
Eric Laurent150dbfe2013-02-27 14:31:02 -08001768 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001769 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770
1771 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001772 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001774 list_remove(&uc_info->list);
1775 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001777 adev->active_input = get_next_active_input(adev);
1778
Eric Laurent994a6932013-07-17 11:51:42 -07001779 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 return ret;
1781}
1782
1783int start_input_stream(struct stream_in *in)
1784{
1785 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001786 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 struct audio_usecase *uc_info;
1788 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301789 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Mingming Yin2664a5b2015-09-03 10:53:11 -07001791 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1792 if (get_usecase_from_list(adev, usecase) == NULL)
1793 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301794 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1795 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001796
Naresh Tanniru80659832014-06-04 18:17:56 +05301797
1798 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301799 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301800 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301801 goto error_config;
1802 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301803
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001804 /* Check if source matches incall recording usecase criteria */
1805 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1806 if (ret)
1807 goto error_config;
1808 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001809 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1810
1811 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1812 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1813 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001814 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001815 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001816
Eric Laurentb23d5282013-05-14 15:27:20 -07001817 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 if (in->pcm_device_id < 0) {
1819 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1820 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001821 ret = -EINVAL;
1822 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824
1825 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001827
1828 if (!uc_info) {
1829 ret = -ENOMEM;
1830 goto error_config;
1831 }
1832
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 uc_info->id = in->usecase;
1834 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001835 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 uc_info->devices = in->device;
1837 uc_info->in_snd_device = SND_DEVICE_NONE;
1838 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001840 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301841 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1842 adev->perf_lock_opts,
1843 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001844 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301846 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1847 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001848
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301849 if (audio_extn_cin_attached_usecase(in->usecase)) {
1850 ret = audio_extn_cin_start_input_stream(in);
1851 if (ret)
1852 goto error_open;
1853 else
1854 goto done_open;
1855 }
1856
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001857 unsigned int flags = PCM_IN;
1858 unsigned int pcm_open_retry_count = 0;
1859
1860 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1861 flags |= PCM_MMAP | PCM_NOIRQ;
1862 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001863 } else if (in->realtime) {
1864 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001865 }
1866
1867 while (1) {
1868 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1869 flags, &in->config);
1870 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1871 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1872 if (in->pcm != NULL) {
1873 pcm_close(in->pcm);
1874 in->pcm = NULL;
1875 }
1876 if (pcm_open_retry_count-- == 0) {
1877 ret = -EIO;
1878 goto error_open;
1879 }
1880 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1881 continue;
1882 }
1883 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001885
1886 ALOGV("%s: pcm_prepare", __func__);
1887 ret = pcm_prepare(in->pcm);
1888 if (ret < 0) {
1889 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1890 pcm_close(in->pcm);
1891 in->pcm = NULL;
1892 goto error_open;
1893 }
1894
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001895 register_in_stream(in);
1896 if (in->realtime) {
1897 ret = pcm_start(in->pcm);
1898 if (ret < 0)
1899 goto error_open;
1900 }
1901
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301902done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301903 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001904 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001905
Eric Laurentc8400632013-02-14 19:04:54 -08001906 return ret;
1907
1908error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301909 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001911error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301912 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301913 /*
1914 * sleep 50ms to allow sufficient time for kernel
1915 * drivers to recover incases like SSR.
1916 */
1917 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001918 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001919
1920 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921}
1922
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001923void lock_input_stream(struct stream_in *in)
1924{
1925 pthread_mutex_lock(&in->pre_lock);
1926 pthread_mutex_lock(&in->lock);
1927 pthread_mutex_unlock(&in->pre_lock);
1928}
1929
1930void lock_output_stream(struct stream_out *out)
1931{
1932 pthread_mutex_lock(&out->pre_lock);
1933 pthread_mutex_lock(&out->lock);
1934 pthread_mutex_unlock(&out->pre_lock);
1935}
1936
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001937/* must be called with out->lock locked */
1938static int send_offload_cmd_l(struct stream_out* out, int command)
1939{
1940 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1941
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001942 if (!cmd) {
1943 ALOGE("failed to allocate mem for command 0x%x", command);
1944 return -ENOMEM;
1945 }
1946
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001947 ALOGVV("%s %d", __func__, command);
1948
1949 cmd->cmd = command;
1950 list_add_tail(&out->offload_cmd_list, &cmd->node);
1951 pthread_cond_signal(&out->offload_cond);
1952 return 0;
1953}
1954
1955/* must be called iwth out->lock locked */
1956static void stop_compressed_output_l(struct stream_out *out)
1957{
1958 out->offload_state = OFFLOAD_STATE_IDLE;
1959 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001960 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001961 if (out->compr != NULL) {
1962 compress_stop(out->compr);
1963 while (out->offload_thread_blocked) {
1964 pthread_cond_wait(&out->cond, &out->lock);
1965 }
1966 }
1967}
1968
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001969bool is_offload_usecase(audio_usecase_t uc_id)
1970{
1971 unsigned int i;
1972 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1973 if (uc_id == offload_usecases[i])
1974 return true;
1975 }
1976 return false;
1977}
1978
Dhananjay Kumarac341582017-02-23 23:42:25 +05301979static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001980{
vivek mehta446c3962015-09-14 10:57:35 -07001981 audio_usecase_t ret_uc = USECASE_INVALID;
1982 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001983 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001984 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301985 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001986 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1987 else
1988 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001989
vivek mehta446c3962015-09-14 10:57:35 -07001990 pthread_mutex_lock(&adev->lock);
1991 if (get_usecase_from_list(adev, ret_uc) != NULL)
1992 ret_uc = USECASE_INVALID;
1993 pthread_mutex_unlock(&adev->lock);
1994
1995 return ret_uc;
1996 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001997
1998 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001999 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2000 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2001 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2002 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002003 break;
2004 }
2005 }
vivek mehta446c3962015-09-14 10:57:35 -07002006
2007 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2008 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002009}
2010
2011static void free_offload_usecase(struct audio_device *adev,
2012 audio_usecase_t uc_id)
2013{
vivek mehta446c3962015-09-14 10:57:35 -07002014 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002015 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002016
2017 if (!adev->multi_offload_enable)
2018 return;
2019
2020 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2021 if (offload_usecases[offload_uc_index] == uc_id) {
2022 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002023 break;
2024 }
2025 }
2026 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2027}
2028
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029static void *offload_thread_loop(void *context)
2030{
2031 struct stream_out *out = (struct stream_out *) context;
2032 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002033 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002034
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2036 set_sched_policy(0, SP_FOREGROUND);
2037 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2038
2039 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002040 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002041 for (;;) {
2042 struct offload_cmd *cmd = NULL;
2043 stream_callback_event_t event;
2044 bool send_callback = false;
2045
2046 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2047 __func__, list_empty(&out->offload_cmd_list),
2048 out->offload_state);
2049 if (list_empty(&out->offload_cmd_list)) {
2050 ALOGV("%s SLEEPING", __func__);
2051 pthread_cond_wait(&out->offload_cond, &out->lock);
2052 ALOGV("%s RUNNING", __func__);
2053 continue;
2054 }
2055
2056 item = list_head(&out->offload_cmd_list);
2057 cmd = node_to_item(item, struct offload_cmd, node);
2058 list_remove(item);
2059
2060 ALOGVV("%s STATE %d CMD %d out->compr %p",
2061 __func__, out->offload_state, cmd->cmd, out->compr);
2062
2063 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2064 free(cmd);
2065 break;
2066 }
2067
2068 if (out->compr == NULL) {
2069 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002070 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002071 pthread_cond_signal(&out->cond);
2072 continue;
2073 }
2074 out->offload_thread_blocked = true;
2075 pthread_mutex_unlock(&out->lock);
2076 send_callback = false;
2077 switch(cmd->cmd) {
2078 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002079 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002080 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002081 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 send_callback = true;
2083 event = STREAM_CBK_EVENT_WRITE_READY;
2084 break;
2085 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002086 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302087 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002088 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302089 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002090 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302091 if (ret < 0)
2092 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302093 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302094 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002095 compress_drain(out->compr);
2096 else
2097 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302098 if (ret != -ENETRESET) {
2099 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302100 pthread_mutex_lock(&out->lock);
2101 out->send_new_metadata = 1;
2102 out->send_next_track_params = true;
2103 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302104 event = STREAM_CBK_EVENT_DRAIN_READY;
2105 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2106 } else
2107 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 break;
2109 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002110 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002112 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113 send_callback = true;
2114 event = STREAM_CBK_EVENT_DRAIN_READY;
2115 break;
2116 default:
2117 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2118 break;
2119 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002120 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002121 out->offload_thread_blocked = false;
2122 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002123 if (send_callback && out->client_callback) {
2124 ALOGVV("%s: sending client_callback event %d", __func__, event);
2125 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002126 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 free(cmd);
2128 }
2129
2130 pthread_cond_signal(&out->cond);
2131 while (!list_empty(&out->offload_cmd_list)) {
2132 item = list_head(&out->offload_cmd_list);
2133 list_remove(item);
2134 free(node_to_item(item, struct offload_cmd, node));
2135 }
2136 pthread_mutex_unlock(&out->lock);
2137
2138 return NULL;
2139}
2140
2141static int create_offload_callback_thread(struct stream_out *out)
2142{
2143 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2144 list_init(&out->offload_cmd_list);
2145 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2146 offload_thread_loop, out);
2147 return 0;
2148}
2149
2150static int destroy_offload_callback_thread(struct stream_out *out)
2151{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002152 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 stop_compressed_output_l(out);
2154 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2155
2156 pthread_mutex_unlock(&out->lock);
2157 pthread_join(out->offload_thread, (void **) NULL);
2158 pthread_cond_destroy(&out->offload_cond);
2159
2160 return 0;
2161}
2162
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163static int stop_output_stream(struct stream_out *out)
2164{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302165 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 struct audio_usecase *uc_info;
2167 struct audio_device *adev = out->dev;
2168
Eric Laurent994a6932013-07-17 11:51:42 -07002169 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002170 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 uc_info = get_usecase_from_list(adev, out->usecase);
2172 if (uc_info == NULL) {
2173 ALOGE("%s: Could not find the usecase (%d) in the list",
2174 __func__, out->usecase);
2175 return -EINVAL;
2176 }
2177
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002178 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302179 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002180 if (adev->visualizer_stop_output != NULL)
2181 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002182
2183 audio_extn_dts_remove_state_notifier_node(out->usecase);
2184
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002185 if (adev->offload_effects_stop_output != NULL)
2186 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2187 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002188
Eric Laurent150dbfe2013-02-27 14:31:02 -08002189 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002190 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002191
2192 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002193 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002195 list_remove(&uc_info->list);
2196 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002198 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302199 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002200 ALOGV("Disable passthrough , reset mixer to pcm");
2201 /* NO_PASSTHROUGH */
2202 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002203 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002204 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2205 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002206
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302207 /* Must be called after removing the usecase from list */
2208 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302209 audio_extn_keep_alive_start();
2210
Eric Laurent994a6932013-07-17 11:51:42 -07002211 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 return ret;
2213}
2214
2215int start_output_stream(struct stream_out *out)
2216{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 struct audio_usecase *uc_info;
2219 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302220 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002221 char mixer_ctl_name[128];
2222 struct mixer_ctl *ctl = NULL;
2223 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002225 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2226 ret = -EINVAL;
2227 goto error_config;
2228 }
2229
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302230 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2231 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2232 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302233
Naresh Tanniru80659832014-06-04 18:17:56 +05302234 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302235 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302236 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302237 goto error_config;
2238 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302239
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302240 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2241 if (!audio_extn_a2dp_is_ready()) {
2242 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2243 //combo usecase just by pass a2dp
2244 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2245 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2246 } else {
2247 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2248 ret = -EAGAIN;
2249 goto error_config;
2250 }
2251 }
2252 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002253 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 if (out->pcm_device_id < 0) {
2255 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2256 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002257 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002258 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 }
2260
2261 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002262
2263 if (!uc_info) {
2264 ret = -ENOMEM;
2265 goto error_config;
2266 }
2267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268 uc_info->id = out->usecase;
2269 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002270 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002271 uc_info->devices = out->devices;
2272 uc_info->in_snd_device = SND_DEVICE_NONE;
2273 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002274 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302276 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2277 adev->perf_lock_opts,
2278 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302279
2280 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2281 audio_extn_keep_alive_stop();
2282 if (audio_extn_passthru_is_enabled() &&
2283 audio_extn_passthru_is_passthrough_stream(out)) {
2284 audio_extn_passthru_on_start(out);
2285 audio_extn_passthru_update_stream_configuration(adev, out);
2286 }
2287 }
2288
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002289 select_devices(adev, out->usecase);
2290
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002291 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2292 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002293 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002294 unsigned int flags = PCM_OUT;
2295 unsigned int pcm_open_retry_count = 0;
2296 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2297 flags |= PCM_MMAP | PCM_NOIRQ;
2298 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002299 } else if (out->realtime) {
2300 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002301 } else
2302 flags |= PCM_MONOTONIC;
2303
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002304 if ((adev->vr_audio_mode_enabled) &&
2305 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2306 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2307 "PCM_Dev %d Topology", out->pcm_device_id);
2308 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2309 if (!ctl) {
2310 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2311 __func__, mixer_ctl_name);
2312 } else {
2313 //if success use ULLPP
2314 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2315 __func__, mixer_ctl_name, out->pcm_device_id);
2316 //There is a still a possibility that some sessions
2317 // that request for FAST|RAW when 3D audio is active
2318 //can go through ULLPP. Ideally we expects apps to
2319 //listen to audio focus and stop concurrent playback
2320 //Also, we will look for mode flag (voice_in_communication)
2321 //before enabling the realtime flag.
2322 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2323 }
2324 }
2325
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002326 while (1) {
2327 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2328 flags, &out->config);
2329 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2330 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2331 if (out->pcm != NULL) {
2332 pcm_close(out->pcm);
2333 out->pcm = NULL;
2334 }
2335 if (pcm_open_retry_count-- == 0) {
2336 ret = -EIO;
2337 goto error_open;
2338 }
2339 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2340 continue;
2341 }
2342 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002344
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002345 ALOGV("%s: pcm_prepare", __func__);
2346 if (pcm_is_ready(out->pcm)) {
2347 ret = pcm_prepare(out->pcm);
2348 if (ret < 0) {
2349 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2350 pcm_close(out->pcm);
2351 out->pcm = NULL;
2352 goto error_open;
2353 }
2354 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302355 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302356 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2357
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002358 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002359 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302360 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002362 out->compr = compress_open(adev->snd_card,
2363 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 COMPRESS_IN, &out->compr_config);
2365 if (out->compr && !is_compress_ready(out->compr)) {
2366 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2367 compress_close(out->compr);
2368 out->compr = NULL;
2369 ret = -EIO;
2370 goto error_open;
2371 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302372 /* compress_open sends params of the track, so reset the flag here */
2373 out->is_compr_metadata_avail = false;
2374
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002375 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002377
Fred Oh3f43e742015-03-04 18:42:34 -08002378 /* Since small bufs uses blocking writes, a write will be blocked
2379 for the default max poll time (20s) in the event of an SSR.
2380 Reduce the poll time to observe and deal with SSR faster.
2381 */
Ashish Jain5106d362016-05-11 19:23:33 +05302382 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002383 compress_set_max_poll_wait(out->compr, 1000);
2384 }
2385
Manish Dewangan69426c82017-01-30 17:35:36 +05302386 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302387 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302388
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002389 audio_extn_dts_create_state_notifier_node(out->usecase);
2390 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2391 popcount(out->channel_mask),
2392 out->playback_started);
2393
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002394#ifdef DS1_DOLBY_DDP_ENABLED
2395 if (audio_extn_is_dolby_format(out->format))
2396 audio_extn_dolby_send_ddp_endp_params(adev);
2397#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302398 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2399 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002400 if (adev->visualizer_start_output != NULL)
2401 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2402 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302403 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002404 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002405 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002406 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002407
2408 if (ret == 0) {
2409 register_out_stream(out);
2410 if (out->realtime) {
2411 ret = pcm_start(out->pcm);
2412 if (ret < 0)
2413 goto error_open;
2414 }
2415 }
2416
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302417 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002418 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002419
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002420 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002421error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302422 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002424error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302425 /*
2426 * sleep 50ms to allow sufficient time for kernel
2427 * drivers to recover incases like SSR.
2428 */
2429 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002430 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431}
2432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433static int check_input_parameters(uint32_t sample_rate,
2434 audio_format_t format,
2435 int channel_count)
2436{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002437 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302439 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2440 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2441 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002442 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302443 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002444
2445 switch (channel_count) {
2446 case 1:
2447 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302448 case 3:
2449 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002450 case 6:
2451 break;
2452 default:
2453 ret = -EINVAL;
2454 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455
2456 switch (sample_rate) {
2457 case 8000:
2458 case 11025:
2459 case 12000:
2460 case 16000:
2461 case 22050:
2462 case 24000:
2463 case 32000:
2464 case 44100:
2465 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302466 case 96000:
2467 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 break;
2469 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002470 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 }
2472
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002473 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474}
2475
2476static size_t get_input_buffer_size(uint32_t sample_rate,
2477 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002478 int channel_count,
2479 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480{
2481 size_t size = 0;
2482
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002483 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2484 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002486 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002487 if (is_low_latency)
2488 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302489
2490 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002492 /* make sure the size is multiple of 32 bytes
2493 * At 48 kHz mono 16-bit PCM:
2494 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2495 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2496 */
2497 size += 0x1f;
2498 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002499
2500 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501}
2502
Ashish Jain058165c2016-09-28 23:18:48 +05302503static size_t get_output_period_size(uint32_t sample_rate,
2504 audio_format_t format,
2505 int channel_count,
2506 int duration /*in millisecs*/)
2507{
2508 size_t size = 0;
2509 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2510
2511 if ((duration == 0) || (sample_rate == 0) ||
2512 (bytes_per_sample == 0) || (channel_count == 0)) {
2513 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2514 bytes_per_sample, channel_count);
2515 return -EINVAL;
2516 }
2517
2518 size = (sample_rate *
2519 duration *
2520 bytes_per_sample *
2521 channel_count) / 1000;
2522 /*
2523 * To have same PCM samples for all channels, the buffer size requires to
2524 * be multiple of (number of channels * bytes per sample)
2525 * For writes to succeed, the buffer must be written at address which is multiple of 32
2526 */
2527 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2528
2529 return (size/(channel_count * bytes_per_sample));
2530}
2531
Ashish Jain5106d362016-05-11 19:23:33 +05302532static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2533{
2534 uint64_t actual_frames_rendered = 0;
2535 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2536
2537 /* This adjustment accounts for buffering after app processor.
2538 * It is based on estimated DSP latency per use case, rather than exact.
2539 */
2540 int64_t platform_latency = platform_render_latency(out->usecase) *
2541 out->sample_rate / 1000000LL;
2542
2543 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2544 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2545 * hence only estimate.
2546 */
2547 int64_t signed_frames = out->written - kernel_buffer_size;
2548
2549 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2550
2551 if (signed_frames > 0)
2552 actual_frames_rendered = signed_frames;
2553
2554 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2555 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2556 (long long int)out->written, (int)kernel_buffer_size,
2557 audio_bytes_per_sample(out->compr_config.codec->format),
2558 popcount(out->channel_mask));
2559
2560 return actual_frames_rendered;
2561}
2562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002563static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568}
2569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002570static int out_set_sample_rate(struct audio_stream *stream __unused,
2571 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572{
2573 return -ENOSYS;
2574}
2575
2576static size_t out_get_buffer_size(const struct audio_stream *stream)
2577{
2578 struct stream_out *out = (struct stream_out *)stream;
2579
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302580 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2581 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2582 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2583 else
2584 return out->compr_config.fragment_size;
2585 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002586 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302587 else if (is_offload_usecase(out->usecase) &&
2588 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302589 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002590
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002591 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002592 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593}
2594
2595static uint32_t out_get_channels(const struct audio_stream *stream)
2596{
2597 struct stream_out *out = (struct stream_out *)stream;
2598
2599 return out->channel_mask;
2600}
2601
2602static audio_format_t out_get_format(const struct audio_stream *stream)
2603{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002604 struct stream_out *out = (struct stream_out *)stream;
2605
2606 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607}
2608
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002609static int out_set_format(struct audio_stream *stream __unused,
2610 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611{
2612 return -ENOSYS;
2613}
2614
2615static int out_standby(struct audio_stream *stream)
2616{
2617 struct stream_out *out = (struct stream_out *)stream;
2618 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002619
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302620 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2621 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002623 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002625 if (adev->adm_deregister_stream)
2626 adev->adm_deregister_stream(adev->adm_data, out->handle);
2627
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002628 if (is_offload_usecase(out->usecase))
2629 stop_compressed_output_l(out);
2630
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002631 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002633 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2634 voice_extn_compress_voip_close_output_stream(stream);
2635 pthread_mutex_unlock(&adev->lock);
2636 pthread_mutex_unlock(&out->lock);
2637 ALOGD("VOIP output entered standby");
2638 return 0;
2639 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002640 if (out->pcm) {
2641 pcm_close(out->pcm);
2642 out->pcm = NULL;
2643 }
2644 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002645 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302646 out->send_next_track_params = false;
2647 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002648 out->gapless_mdata.encoder_delay = 0;
2649 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002650 if (out->compr != NULL) {
2651 compress_close(out->compr);
2652 out->compr = NULL;
2653 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002656 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 }
2658 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302659 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 return 0;
2661}
2662
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002663static int out_dump(const struct audio_stream *stream __unused,
2664 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665{
2666 return 0;
2667}
2668
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002669static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2670{
2671 int ret = 0;
2672 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002673
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002674 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002675 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002676 return -EINVAL;
2677 }
2678
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302679 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002680
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002681 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2682 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302683 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002684 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002685 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2686 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302687 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002688 }
2689
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002690 ALOGV("%s new encoder delay %u and padding %u", __func__,
2691 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2692
2693 return 0;
2694}
2695
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002696static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2697{
2698 return out == adev->primary_output || out == adev->voice_tx_output;
2699}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2702{
2703 struct stream_out *out = (struct stream_out *)stream;
2704 struct audio_device *adev = out->dev;
2705 struct str_parms *parms;
2706 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002707 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708
sangwoobc677242013-08-08 16:53:43 +09002709 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002710 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302712 if (!parms)
2713 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002714 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2715 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002717 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002718 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002720 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002721 * When HDMI cable is unplugged the music playback is paused and
2722 * the policy manager sends routing=0. But the audioflinger continues
2723 * to write data until standby time (3sec). As the HDMI core is
2724 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002725 * Avoid this by routing audio to speaker until standby.
2726 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002727 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2728 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302729 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002730 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2731 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002732 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302733 /*
2734 * When A2DP is disconnected the
2735 * music playback is paused and the policy manager sends routing=0
2736 * But the audioflingercontinues to write data until standby time
2737 * (3sec). As BT is turned off, the write gets blocked.
2738 * Avoid this by routing audio to speaker until standby.
2739 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002740 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302741 (val == AUDIO_DEVICE_NONE)) {
2742 val = AUDIO_DEVICE_OUT_SPEAKER;
2743 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302744 /* To avoid a2dp to sco overlapping / BT device improper state
2745 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302746 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302747 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2748 if (!audio_extn_a2dp_is_ready()) {
2749 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2750 //combo usecase just by pass a2dp
2751 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2752 val = AUDIO_DEVICE_OUT_SPEAKER;
2753 } else {
2754 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2755 /* update device to a2dp and don't route as BT returned error
2756 * However it is still possible a2dp routing called because
2757 * of current active device disconnection (like wired headset)
2758 */
2759 out->devices = val;
2760 pthread_mutex_unlock(&out->lock);
2761 pthread_mutex_unlock(&adev->lock);
2762 goto error;
2763 }
2764 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302765 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002766 /*
2767 * select_devices() call below switches all the usecases on the same
2768 * backend to the new device. Refer to check_usecases_codec_backend() in
2769 * the select_devices(). But how do we undo this?
2770 *
2771 * For example, music playback is active on headset (deep-buffer usecase)
2772 * and if we go to ringtones and select a ringtone, low-latency usecase
2773 * will be started on headset+speaker. As we can't enable headset+speaker
2774 * and headset devices at the same time, select_devices() switches the music
2775 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2776 * So when the ringtone playback is completed, how do we undo the same?
2777 *
2778 * We are relying on the out_set_parameters() call on deep-buffer output,
2779 * once the ringtone playback is ended.
2780 * NOTE: We should not check if the current devices are same as new devices.
2781 * Because select_devices() must be called to switch back the music
2782 * playback to headset.
2783 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002784 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002785 audio_devices_t new_dev = val;
2786 bool same_dev = out->devices == new_dev;
2787 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002788
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002789 if (output_drives_call(adev, out)) {
2790 if(!voice_is_in_call(adev)) {
2791 if (adev->mode == AUDIO_MODE_IN_CALL) {
2792 adev->current_call_output = out;
2793 ret = voice_start_call(adev);
2794 }
2795 } else {
2796 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002797 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002798 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002799 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002800
2801 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002802 if (!same_dev) {
2803 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302804 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2805 adev->perf_lock_opts,
2806 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002807 if (adev->adm_on_routing_change)
2808 adev->adm_on_routing_change(adev->adm_data,
2809 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002810 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002811 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302812 if (!same_dev)
2813 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002814 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002815 }
2816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002818 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002820
2821 if (out == adev->primary_output) {
2822 pthread_mutex_lock(&adev->lock);
2823 audio_extn_set_parameters(adev, parms);
2824 pthread_mutex_unlock(&adev->lock);
2825 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002826 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002827 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002828 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002829
2830 audio_extn_dts_create_state_notifier_node(out->usecase);
2831 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2832 popcount(out->channel_mask),
2833 out->playback_started);
2834
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002835 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002836 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002837
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302838 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2839 if (err >= 0) {
2840 strlcpy(out->profile, value, sizeof(out->profile));
2841 ALOGV("updating stream profile with value '%s'", out->profile);
2842 lock_output_stream(out);
2843 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2844 &adev->streams_output_cfg_list,
2845 out->devices, out->flags, out->format,
2846 out->sample_rate, out->bit_width,
2847 out->channel_mask, out->profile,
2848 &out->app_type_cfg);
2849 pthread_mutex_unlock(&out->lock);
2850 }
2851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302853error:
Eric Laurent994a6932013-07-17 11:51:42 -07002854 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855 return ret;
2856}
2857
2858static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2859{
2860 struct stream_out *out = (struct stream_out *)stream;
2861 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002862 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 char value[256];
2864 struct str_parms *reply = str_parms_create();
2865 size_t i, j;
2866 int ret;
2867 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002868
2869 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002870 if (reply) {
2871 str_parms_destroy(reply);
2872 }
2873 if (query) {
2874 str_parms_destroy(query);
2875 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002876 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2877 return NULL;
2878 }
2879
Eric Laurent994a6932013-07-17 11:51:42 -07002880 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002881 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2882 if (ret >= 0) {
2883 value[0] = '\0';
2884 i = 0;
2885 while (out->supported_channel_masks[i] != 0) {
2886 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2887 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2888 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002889 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002891 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892 first = false;
2893 break;
2894 }
2895 }
2896 i++;
2897 }
2898 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2899 str = str_parms_to_str(reply);
2900 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002901 voice_extn_out_get_parameters(out, query, reply);
2902 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002903 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002904 free(str);
2905 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002906 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002908
Alexy Joseph62142aa2015-11-16 15:10:34 -08002909
2910 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2911 if (ret >= 0) {
2912 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302913 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2914 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002915 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302916 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002917 } else {
2918 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302919 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002920 }
2921 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002922 if (str)
2923 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002924 str = str_parms_to_str(reply);
2925 }
2926
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002927 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2928 if (ret >= 0) {
2929 value[0] = '\0';
2930 i = 0;
2931 first = true;
2932 while (out->supported_formats[i] != 0) {
2933 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2934 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2935 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002936 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002937 }
2938 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2939 first = false;
2940 break;
2941 }
2942 }
2943 i++;
2944 }
2945 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002946 if (str)
2947 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002948 str = str_parms_to_str(reply);
2949 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002950
2951 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2952 if (ret >= 0) {
2953 value[0] = '\0';
2954 i = 0;
2955 first = true;
2956 while (out->supported_sample_rates[i] != 0) {
2957 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2958 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2959 if (!first) {
2960 strlcat(value, "|", sizeof(value));
2961 }
2962 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2963 first = false;
2964 break;
2965 }
2966 }
2967 i++;
2968 }
2969 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2970 if (str)
2971 free(str);
2972 str = str_parms_to_str(reply);
2973 }
2974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 str_parms_destroy(query);
2976 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002977 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 return str;
2979}
2980
2981static uint32_t out_get_latency(const struct audio_stream_out *stream)
2982{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002983 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002985 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986
Alexy Josephaa54c872014-12-03 02:46:47 -08002987 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302988 lock_output_stream(out);
2989 latency = audio_extn_utils_compress_get_dsp_latency(out);
2990 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002991 } else if (out->realtime) {
2992 // since the buffer won't be filled up faster than realtime,
2993 // return a smaller number
2994 if (out->config.rate)
2995 period_ms = (out->af_period_multiplier * out->config.period_size *
2996 1000) / (out->config.rate);
2997 else
2998 period_ms = 0;
2999 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003000 } else {
3001 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003002 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003003 }
3004
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003005 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3006 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3007 latency += audio_extn_a2dp_get_encoder_latency();
3008
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303009 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003010 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011}
3012
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303013static float AmpToDb(float amplification)
3014{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303015 float db = DSD_VOLUME_MIN_DB;
3016 if (amplification > 0) {
3017 db = 20 * log10(amplification);
3018 if(db < DSD_VOLUME_MIN_DB)
3019 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303020 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303021 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303022}
3023
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024static int out_set_volume(struct audio_stream_out *stream, float left,
3025 float right)
3026{
Eric Laurenta9024de2013-04-04 09:19:12 -07003027 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003028 int volume[2];
3029
Eric Laurenta9024de2013-04-04 09:19:12 -07003030 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3031 /* only take left channel into account: the API is for stereo anyway */
3032 out->muted = (left == 0.0f);
3033 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003034 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303035 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003036 /*
3037 * Set mute or umute on HDMI passthrough stream.
3038 * Only take left channel into account.
3039 * Mute is 0 and unmute 1
3040 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303041 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303042 } else if (out->format == AUDIO_FORMAT_DSD){
3043 char mixer_ctl_name[128] = "DSD Volume";
3044 struct audio_device *adev = out->dev;
3045 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3046
3047 if (!ctl) {
3048 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3049 __func__, mixer_ctl_name);
3050 return -EINVAL;
3051 }
3052 volume[0] = (int)(AmpToDb(left));
3053 volume[1] = (int)(AmpToDb(right));
3054 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3055 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003056 } else {
3057 char mixer_ctl_name[128];
3058 struct audio_device *adev = out->dev;
3059 struct mixer_ctl *ctl;
3060 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003061 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003062
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003063 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3064 "Compress Playback %d Volume", pcm_device_id);
3065 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3066 if (!ctl) {
3067 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3068 __func__, mixer_ctl_name);
3069 return -EINVAL;
3070 }
3071 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3072 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3073 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3074 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003075 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003076 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 return -ENOSYS;
3079}
3080
3081static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3082 size_t bytes)
3083{
3084 struct stream_out *out = (struct stream_out *)stream;
3085 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303086 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003087 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003089 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303090
Naresh Tanniru80659832014-06-04 18:17:56 +05303091 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003092
Dhananjay Kumarac341582017-02-23 23:42:25 +05303093 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303094 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303095 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3096 pthread_mutex_unlock(&out->lock);
3097 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303098 } else {
3099 /* increase written size during SSR to avoid mismatch
3100 * with the written frames count in AF
3101 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003102 // bytes per frame
3103 size_t bpf = audio_bytes_per_sample(out->format) *
3104 audio_channel_count_from_out_mask(out->channel_mask);
3105 if (bpf != 0)
3106 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303107 ALOGD(" %s: sound card is not active/SSR state", __func__);
3108 ret= -EIO;
3109 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303110 }
3111 }
3112
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303113 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303114 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3115 if (audio_bytes_per_sample(out->format) != 0)
3116 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3117 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303118 goto exit;
3119 }
3120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003122 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003123 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003124 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3125 ret = voice_extn_compress_voip_start_output_stream(out);
3126 else
3127 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003128 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003129 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003131 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 goto exit;
3133 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003134
3135 if (last_known_cal_step != -1) {
3136 ALOGD("%s: retry previous failed cal level set", __func__);
3137 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140
Ashish Jain81eb2a82015-05-13 10:52:34 +05303141 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003142 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303143 adev->is_channel_status_set = true;
3144 }
3145
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003146 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003147 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003148 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003149 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003150 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3151 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303152 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3153 ALOGD("copl(%p):send next track params in gapless", out);
3154 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3155 out->send_next_track_params = false;
3156 out->is_compr_metadata_avail = false;
3157 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003158 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303159 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303160 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003161
Ashish Jain83a6cc22016-06-28 14:34:17 +05303162 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303163 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303164 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303165 pthread_mutex_unlock(&out->lock);
3166 return -EINVAL;
3167 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303168 audio_format_t dst_format = out->hal_op_format;
3169 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303170
3171 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3172 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3173
Ashish Jain83a6cc22016-06-28 14:34:17 +05303174 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303175 dst_format,
3176 buffer,
3177 src_format,
3178 frames);
3179
Ashish Jain83a6cc22016-06-28 14:34:17 +05303180 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303181 bytes_to_write);
3182
3183 /*Convert written bytes in audio flinger format*/
3184 if (ret > 0)
3185 ret = ((ret * format_to_bitwidth_table[out->format]) /
3186 format_to_bitwidth_table[dst_format]);
3187 }
3188 } else
3189 ret = compress_write(out->compr, buffer, bytes);
3190
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303191 if (ret < 0)
3192 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303193 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303194 /*msg to cb thread only if non blocking write is enabled*/
3195 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303196 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003197 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303198 } else if (-ENETRESET == ret) {
3199 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3200 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3201 pthread_mutex_unlock(&out->lock);
3202 out_standby(&out->stream.common);
3203 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003204 }
Ashish Jain5106d362016-05-11 19:23:33 +05303205 if ( ret == (ssize_t)bytes && !out->non_blocking)
3206 out->written += bytes;
3207
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303208 /* Call compr start only when non-zero bytes of data is there to be rendered */
3209 if (!out->playback_started && ret > 0) {
3210 int status = compress_start(out->compr);
3211 if (status < 0) {
3212 ret = status;
3213 ALOGE("%s: compr start failed with err %d", __func__, errno);
3214 goto exit;
3215 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003216 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003217 out->playback_started = 1;
3218 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003219
3220 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3221 popcount(out->channel_mask),
3222 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003223 }
3224 pthread_mutex_unlock(&out->lock);
3225 return ret;
3226 } else {
3227 if (out->pcm) {
3228 if (out->muted)
3229 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003230
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303231 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003232
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003233 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003234
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003235 if (out->config.rate)
3236 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3237 out->config.rate;
3238
3239 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3240
3241 request_out_focus(out, ns);
3242
3243 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003244 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003245 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303246 out->convert_buffer != NULL) {
3247
3248 memcpy_by_audio_format(out->convert_buffer,
3249 out->hal_op_format,
3250 buffer,
3251 out->hal_ip_format,
3252 out->config.period_size * out->config.channels);
3253
3254 ret = pcm_write(out->pcm, out->convert_buffer,
3255 (out->config.period_size *
3256 out->config.channels *
3257 format_to_bitwidth_table[out->hal_op_format]));
3258 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003259 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303260 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003261
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003262 release_out_focus(out);
3263
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303264 if (ret < 0)
3265 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303266 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3267 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3268 else
3269 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 }
3272
3273exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303274 /* ToDo: There may be a corner case when SSR happens back to back during
3275 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303276 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303277 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303278 }
3279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 pthread_mutex_unlock(&out->lock);
3281
3282 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003283 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003284 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303285 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303286 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303287 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303288 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303289 out->standby = true;
3290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303292 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3293 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3294 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 }
3296 return bytes;
3297}
3298
3299static int out_get_render_position(const struct audio_stream_out *stream,
3300 uint32_t *dsp_frames)
3301{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003302 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303303 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003304
3305 if (dsp_frames == NULL)
3306 return -EINVAL;
3307
3308 *dsp_frames = 0;
3309 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003310 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303311
3312 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3313 * this operation and adev_close_output_stream(where out gets reset).
3314 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303315 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303316 *dsp_frames = get_actual_pcm_frames_rendered(out);
3317 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3318 return 0;
3319 }
3320
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003321 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303322 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303323 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003324 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303325 if (ret < 0)
3326 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003327 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303328 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003329 }
3330 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303331 if (-ENETRESET == ret) {
3332 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3333 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3334 return -EINVAL;
3335 } else if(ret < 0) {
3336 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3337 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303338 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3339 /*
3340 * Handle corner case where compress session is closed during SSR
3341 * and timestamp is queried
3342 */
3343 ALOGE(" ERROR: sound card not active, return error");
3344 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303345 } else {
3346 return 0;
3347 }
Zhou Song32a556e2015-05-05 10:46:56 +08003348 } else if (audio_is_linear_pcm(out->format)) {
3349 *dsp_frames = out->written;
3350 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 } else
3352 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353}
3354
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003355static int out_add_audio_effect(const struct audio_stream *stream __unused,
3356 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357{
3358 return 0;
3359}
3360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003361static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3362 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363{
3364 return 0;
3365}
3366
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003367static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3368 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369{
3370 return -EINVAL;
3371}
3372
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003373static int out_get_presentation_position(const struct audio_stream_out *stream,
3374 uint64_t *frames, struct timespec *timestamp)
3375{
3376 struct stream_out *out = (struct stream_out *)stream;
3377 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003378 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003379
Ashish Jain5106d362016-05-11 19:23:33 +05303380 /* below piece of code is not guarded against any lock because audioFliner serializes
3381 * this operation and adev_close_output_stream( where out gets reset).
3382 */
3383 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303384 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303385 *frames = get_actual_pcm_frames_rendered(out);
3386 /* this is the best we can do */
3387 clock_gettime(CLOCK_MONOTONIC, timestamp);
3388 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3389 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3390 return 0;
3391 }
3392
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003393 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003394
Ashish Jain5106d362016-05-11 19:23:33 +05303395 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3396 ret = compress_get_tstamp(out->compr, &dsp_frames,
3397 &out->sample_rate);
3398 ALOGVV("%s rendered frames %ld sample_rate %d",
3399 __func__, dsp_frames, out->sample_rate);
3400 *frames = dsp_frames;
3401 if (ret < 0)
3402 ret = -errno;
3403 if (-ENETRESET == ret) {
3404 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3405 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3406 ret = -EINVAL;
3407 } else
3408 ret = 0;
3409 /* this is the best we can do */
3410 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003411 } else {
3412 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003413 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003414 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3415 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003416 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003417 // This adjustment accounts for buffering after app processor.
3418 // It is based on estimated DSP latency per use case, rather than exact.
3419 signed_frames -=
3420 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3421
Eric Laurent949a0892013-09-20 09:20:13 -07003422 // It would be unusual for this value to be negative, but check just in case ...
3423 if (signed_frames >= 0) {
3424 *frames = signed_frames;
3425 ret = 0;
3426 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003427 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303428 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3429 *frames = out->written;
3430 clock_gettime(CLOCK_MONOTONIC, timestamp);
3431 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003432 }
3433 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003434 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003435 return ret;
3436}
3437
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003438static int out_set_callback(struct audio_stream_out *stream,
3439 stream_callback_t callback, void *cookie)
3440{
3441 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003442 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443
3444 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003445 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003446 out->client_callback = callback;
3447 out->client_cookie = cookie;
3448 if (out->adsp_hdlr_stream_handle) {
3449 ret = audio_extn_adsp_hdlr_stream_set_callback(
3450 out->adsp_hdlr_stream_handle,
3451 callback,
3452 cookie);
3453 if (ret)
3454 ALOGW("%s:adsp hdlr callback registration failed %d",
3455 __func__, ret);
3456 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003457 pthread_mutex_unlock(&out->lock);
3458 return 0;
3459}
3460
3461static int out_pause(struct audio_stream_out* stream)
3462{
3463 struct stream_out *out = (struct stream_out *)stream;
3464 int status = -ENOSYS;
3465 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003466 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003467 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003468 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003469 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303470 struct audio_device *adev = out->dev;
3471 int snd_scard_state = get_snd_card_state(adev);
3472
3473 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3474 status = compress_pause(out->compr);
3475
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003477
Mingming Yin21854652016-04-13 11:54:02 -07003478 if (audio_extn_passthru_is_active()) {
3479 ALOGV("offload use case, pause passthru");
3480 audio_extn_passthru_on_pause(out);
3481 }
3482
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303483 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003484 audio_extn_dts_notify_playback_state(out->usecase, 0,
3485 out->sample_rate, popcount(out->channel_mask),
3486 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003487 }
3488 pthread_mutex_unlock(&out->lock);
3489 }
3490 return status;
3491}
3492
3493static int out_resume(struct audio_stream_out* stream)
3494{
3495 struct stream_out *out = (struct stream_out *)stream;
3496 int status = -ENOSYS;
3497 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003498 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003499 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003500 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003501 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303503 struct audio_device *adev = out->dev;
3504 int snd_scard_state = get_snd_card_state(adev);
3505
Mingming Yin21854652016-04-13 11:54:02 -07003506 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3507 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3508 pthread_mutex_lock(&out->dev->lock);
3509 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003510 pthread_mutex_unlock(&out->dev->lock);
3511 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303512 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003513 }
3514 if (!status) {
3515 out->offload_state = OFFLOAD_STATE_PLAYING;
3516 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303517 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003518 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3519 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003520 }
3521 pthread_mutex_unlock(&out->lock);
3522 }
3523 return status;
3524}
3525
3526static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3527{
3528 struct stream_out *out = (struct stream_out *)stream;
3529 int status = -ENOSYS;
3530 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003531 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003532 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003533 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3534 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3535 else
3536 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3537 pthread_mutex_unlock(&out->lock);
3538 }
3539 return status;
3540}
3541
3542static int out_flush(struct audio_stream_out* stream)
3543{
3544 struct stream_out *out = (struct stream_out *)stream;
3545 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003546 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003547 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003548 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003549 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3550 stop_compressed_output_l(out);
3551 out->written = 0;
3552 } else {
3553 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3554 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003556 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003557 return 0;
3558 }
3559 return -ENOSYS;
3560}
3561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562/** audio_stream_in implementation **/
3563static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3564{
3565 struct stream_in *in = (struct stream_in *)stream;
3566
3567 return in->config.rate;
3568}
3569
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003570static int in_set_sample_rate(struct audio_stream *stream __unused,
3571 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572{
3573 return -ENOSYS;
3574}
3575
3576static size_t in_get_buffer_size(const struct audio_stream *stream)
3577{
3578 struct stream_in *in = (struct stream_in *)stream;
3579
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003580 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3581 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003582 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3583 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303584 else if(audio_extn_cin_attached_usecase(in->usecase))
3585 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003586
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003587 return in->config.period_size * in->af_period_multiplier *
3588 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589}
3590
3591static uint32_t in_get_channels(const struct audio_stream *stream)
3592{
3593 struct stream_in *in = (struct stream_in *)stream;
3594
3595 return in->channel_mask;
3596}
3597
3598static audio_format_t in_get_format(const struct audio_stream *stream)
3599{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003600 struct stream_in *in = (struct stream_in *)stream;
3601
3602 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603}
3604
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003605static int in_set_format(struct audio_stream *stream __unused,
3606 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607{
3608 return -ENOSYS;
3609}
3610
3611static int in_standby(struct audio_stream *stream)
3612{
3613 struct stream_in *in = (struct stream_in *)stream;
3614 struct audio_device *adev = in->dev;
3615 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303616 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3617 stream, in->usecase, use_case_table[in->usecase]);
3618
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003619 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003620 if (!in->standby && in->is_st_session) {
3621 ALOGD("%s: sound trigger pcm stop lab", __func__);
3622 audio_extn_sound_trigger_stop_lab(in);
3623 in->standby = 1;
3624 }
3625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003627 if (adev->adm_deregister_stream)
3628 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3629
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003630 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003632 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3633 voice_extn_compress_voip_close_input_stream(stream);
3634 ALOGD("VOIP input entered standby");
3635 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303636 if (audio_extn_cin_attached_usecase(in->usecase))
3637 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003638 if (in->pcm) {
3639 pcm_close(in->pcm);
3640 in->pcm = NULL;
3641 }
3642 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003643 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003644 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 }
3646 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003647 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 return status;
3649}
3650
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003651static int in_dump(const struct audio_stream *stream __unused,
3652 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003653{
3654 return 0;
3655}
3656
3657static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3658{
3659 struct stream_in *in = (struct stream_in *)stream;
3660 struct audio_device *adev = in->dev;
3661 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003663 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303665 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 parms = str_parms_create_str(kvpairs);
3667
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303668 if (!parms)
3669 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003670 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003671 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003672
3673 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3674 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 val = atoi(value);
3676 /* no audio source uses val == 0 */
3677 if ((in->source != val) && (val != 0)) {
3678 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003679 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3680 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3681 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003682 (in->config.rate == 8000 || in->config.rate == 16000 ||
3683 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003684 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003685 err = voice_extn_compress_voip_open_input_stream(in);
3686 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003687 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003688 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003689 }
3690 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 }
3692 }
3693
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003694 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3695 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003697 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698 in->device = val;
3699 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003700 if (!in->standby && !in->is_st_session) {
3701 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003702 if (adev->adm_on_routing_change)
3703 adev->adm_on_routing_change(adev->adm_data,
3704 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003705 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003706 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707 }
3708 }
3709
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303710 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3711 if (err >= 0) {
3712 strlcpy(in->profile, value, sizeof(in->profile));
3713 ALOGV("updating stream profile with value '%s'", in->profile);
3714 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3715 &adev->streams_input_cfg_list,
3716 in->device, in->flags, in->format,
3717 in->sample_rate, in->bit_width,
3718 in->profile, &in->app_type_cfg);
3719 }
3720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003722 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723
3724 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303725error:
Eric Laurent994a6932013-07-17 11:51:42 -07003726 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 return ret;
3728}
3729
3730static char* in_get_parameters(const struct audio_stream *stream,
3731 const char *keys)
3732{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003733 struct stream_in *in = (struct stream_in *)stream;
3734 struct str_parms *query = str_parms_create_str(keys);
3735 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003736 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003737
3738 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003739 if (reply) {
3740 str_parms_destroy(reply);
3741 }
3742 if (query) {
3743 str_parms_destroy(query);
3744 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003745 ALOGE("in_get_parameters: failed to create query or reply");
3746 return NULL;
3747 }
3748
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003749 ALOGV("%s: enter: keys - %s", __func__, keys);
3750
3751 voice_extn_in_get_parameters(in, query, reply);
3752
3753 str = str_parms_to_str(reply);
3754 str_parms_destroy(query);
3755 str_parms_destroy(reply);
3756
3757 ALOGV("%s: exit: returns - %s", __func__, str);
3758 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759}
3760
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003761static int in_set_gain(struct audio_stream_in *stream __unused,
3762 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763{
3764 return 0;
3765}
3766
3767static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3768 size_t bytes)
3769{
3770 struct stream_in *in = (struct stream_in *)stream;
3771 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303772 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303773 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303774 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003776 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303777
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003778 if (in->is_st_session) {
3779 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3780 /* Read from sound trigger HAL */
3781 audio_extn_sound_trigger_read(in, buffer, bytes);
3782 pthread_mutex_unlock(&in->lock);
3783 return bytes;
3784 }
3785
Ashish Jainbbce4322016-02-16 13:25:27 +05303786 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003787 ALOGD(" %s: sound card is not active/SSR state", __func__);
3788 ret= -EIO;;
3789 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303790 }
3791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003793 pthread_mutex_lock(&adev->lock);
3794 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3795 ret = voice_extn_compress_voip_start_input_stream(in);
3796 else
3797 ret = start_input_stream(in);
3798 pthread_mutex_unlock(&adev->lock);
3799 if (ret != 0) {
3800 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 }
3802 in->standby = 0;
3803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003805 // what's the duration requested by the client?
3806 long ns = 0;
3807
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303808 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003809 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3810 in->config.rate;
3811
3812 request_in_focus(in, ns);
3813 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003814
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303815 if (audio_extn_cin_attached_usecase(in->usecase)) {
3816 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3817 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303818 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003819 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303820 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003821 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003822 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003823 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303824 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003825 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303826 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3827 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3828 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3829 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303830 ret = -EINVAL;
3831 goto exit;
3832 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303833 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303834 ret = -errno;
3835 }
3836 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303837 /* bytes read is always set to bytes for non compress usecases */
3838 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 }
3840
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003841 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 /*
3844 * Instead of writing zeroes here, we could trust the hardware
3845 * to always provide zeroes when muted.
3846 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303847 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3848 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 memset(buffer, 0, bytes);
3850
3851exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303852 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303853 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003854 if (-ENETRESET == ret)
3855 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3856
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 pthread_mutex_unlock(&in->lock);
3858
3859 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303860 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303861 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303862 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303863 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303864 in->standby = true;
3865 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303866 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3867 bytes_read = bytes;
3868 memset(buffer, 0, bytes);
3869 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003871 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303872 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303873 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303875 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876}
3877
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003878static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879{
3880 return 0;
3881}
3882
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003883static int add_remove_audio_effect(const struct audio_stream *stream,
3884 effect_handle_t effect,
3885 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003887 struct stream_in *in = (struct stream_in *)stream;
3888 int status = 0;
3889 effect_descriptor_t desc;
3890
3891 status = (*effect)->get_descriptor(effect, &desc);
3892 if (status != 0)
3893 return status;
3894
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003895 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003896 pthread_mutex_lock(&in->dev->lock);
3897 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3898 in->enable_aec != enable &&
3899 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3900 in->enable_aec = enable;
3901 if (!in->standby)
3902 select_devices(in->dev, in->usecase);
3903 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003904 if (in->enable_ns != enable &&
3905 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3906 in->enable_ns = enable;
3907 if (!in->standby)
3908 select_devices(in->dev, in->usecase);
3909 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003910 pthread_mutex_unlock(&in->dev->lock);
3911 pthread_mutex_unlock(&in->lock);
3912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 return 0;
3914}
3915
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003916static int in_add_audio_effect(const struct audio_stream *stream,
3917 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918{
Eric Laurent994a6932013-07-17 11:51:42 -07003919 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003920 return add_remove_audio_effect(stream, effect, true);
3921}
3922
3923static int in_remove_audio_effect(const struct audio_stream *stream,
3924 effect_handle_t effect)
3925{
Eric Laurent994a6932013-07-17 11:51:42 -07003926 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003927 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928}
3929
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303930int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931 audio_io_handle_t handle,
3932 audio_devices_t devices,
3933 audio_output_flags_t flags,
3934 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003935 struct audio_stream_out **stream_out,
3936 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003937{
3938 struct audio_device *adev = (struct audio_device *)dev;
3939 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303940 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003941 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003942 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303945
3946 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3947 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003948 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303949 return -EINVAL;
3950 }
3951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3953
Mingming Yin3a941d42016-02-17 18:08:05 -08003954 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3955 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303956 devices, flags, &out->stream);
3957
3958
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003959 if (!out) {
3960 return -ENOMEM;
3961 }
3962
Haynes Mathew George204045b2015-02-25 20:32:03 -08003963 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003964 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003965 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967 if (devices == AUDIO_DEVICE_NONE)
3968 devices = AUDIO_DEVICE_OUT_SPEAKER;
3969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 out->flags = flags;
3971 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003972 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003973 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003974 out->sample_rate = config->sample_rate;
3975 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3976 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003977 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003978 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003979 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303980 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981
Mingming Yin3a941d42016-02-17 18:08:05 -08003982 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3983 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3984 pthread_mutex_lock(&adev->lock);
3985 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3986 ret = read_hdmi_sink_caps(out);
3987 pthread_mutex_unlock(&adev->lock);
3988 if (ret != 0) {
3989 if (ret == -ENOSYS) {
3990 /* ignore and go with default */
3991 ret = 0;
3992 } else {
3993 ALOGE("error reading hdmi sink caps");
3994 goto error_open;
3995 }
3996 }
3997 }
3998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304000 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004001 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004002 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004003 ret = voice_extn_compress_voip_open_output_stream(out);
4004 if (ret != 0) {
4005 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4006 __func__, ret);
4007 goto error_open;
4008 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004009 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304010 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004011
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004012 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4013 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4014 ALOGE("%s: Unsupported Offload information", __func__);
4015 ret = -EINVAL;
4016 goto error_open;
4017 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004018
Mingming Yin3a941d42016-02-17 18:08:05 -08004019 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004020 if(config->offload_info.format == 0)
4021 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004022 if (config->offload_info.sample_rate == 0)
4023 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004024 }
4025
Mingming Yin90310102013-11-13 16:57:00 -08004026 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304027 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004028 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004029 ret = -EINVAL;
4030 goto error_open;
4031 }
4032
4033 out->compr_config.codec = (struct snd_codec *)
4034 calloc(1, sizeof(struct snd_codec));
4035
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004036 if (!out->compr_config.codec) {
4037 ret = -ENOMEM;
4038 goto error_open;
4039 }
4040
Dhananjay Kumarac341582017-02-23 23:42:25 +05304041 out->stream.pause = out_pause;
4042 out->stream.resume = out_resume;
4043 out->stream.flush = out_flush;
4044 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004045 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004046 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304047 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004048 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304049 } else {
4050 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4051 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004052 }
vivek mehta446c3962015-09-14 10:57:35 -07004053
4054 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004055 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4056 config->format == 0 && config->sample_rate == 0 &&
4057 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004058 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004059 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4060 } else {
4061 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4062 ret = -EEXIST;
4063 goto error_open;
4064 }
vivek mehta446c3962015-09-14 10:57:35 -07004065 }
4066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004067 if (config->offload_info.channel_mask)
4068 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004069 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004070 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004071 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004072 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304073 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004074 ret = -EINVAL;
4075 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004076 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004077
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004078 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004079 out->sample_rate = config->offload_info.sample_rate;
4080
Mingming Yin3ee55c62014-08-04 14:23:35 -07004081 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004082
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304083 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4084 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4085 audio_extn_dolby_send_ddp_endp_params(adev);
4086 audio_extn_dolby_set_dmid(adev);
4087 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004088
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004089 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004090 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004091 out->compr_config.codec->bit_rate =
4092 config->offload_info.bit_rate;
4093 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304094 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004095 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304096 /* Update bit width only for non passthrough usecases.
4097 * For passthrough usecases, the output will always be opened @16 bit
4098 */
4099 if (!audio_extn_passthru_is_passthrough_stream(out))
4100 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304101
4102 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4103 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4104 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4105
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
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304168 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4169 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4170 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004171 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304172 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004173
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304174 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4175 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4176 }
4177
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004178 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4179 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004180
Manish Dewangan69426c82017-01-30 17:35:36 +05304181 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4182 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4183 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4184 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4185 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4186 } else {
4187 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4188 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004189
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304190 memset(&out->channel_map_param, 0,
4191 sizeof(struct audio_out_channel_map_param));
4192
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004193 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304194 out->send_next_track_params = false;
4195 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004196 out->offload_state = OFFLOAD_STATE_IDLE;
4197 out->playback_started = 0;
4198
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004199 audio_extn_dts_create_state_notifier_node(out->usecase);
4200
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004201 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4202 __func__, config->offload_info.version,
4203 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304204
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304205 /* Check if DSD audio format is supported in codec
4206 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304207 */
4208
4209 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304210 (!platform_check_codec_dsd_support(adev->platform) ||
4211 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304212 ret = -EINVAL;
4213 goto error_open;
4214 }
4215
Ashish Jain5106d362016-05-11 19:23:33 +05304216 /* Disable gapless if any of the following is true
4217 * passthrough playback
4218 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304219 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304220 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304221 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304222 (config->format == AUDIO_FORMAT_DSD) ||
4223 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304224 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304225 check_and_set_gapless_mode(adev, false);
4226 } else
4227 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004228
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304229 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004230 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4231 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304232 if (config->format == AUDIO_FORMAT_DSD) {
4233 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4234 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4235 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004236
4237 create_offload_callback_thread(out);
4238
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004239 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304240 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004241 if (ret != 0) {
4242 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4243 __func__, ret);
4244 goto error_open;
4245 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004246 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4247 if (config->sample_rate == 0)
4248 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4249 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4250 config->sample_rate != 8000) {
4251 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4252 ret = -EINVAL;
4253 goto error_open;
4254 }
4255 out->sample_rate = config->sample_rate;
4256 out->config.rate = config->sample_rate;
4257 if (config->format == AUDIO_FORMAT_DEFAULT)
4258 config->format = AUDIO_FORMAT_PCM_16_BIT;
4259 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4260 config->format = AUDIO_FORMAT_PCM_16_BIT;
4261 ret = -EINVAL;
4262 goto error_open;
4263 }
4264 out->format = config->format;
4265 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4266 out->config = pcm_config_afe_proxy_playback;
4267 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004268 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304269 unsigned int channels = 0;
4270 /*Update config params to default if not set by the caller*/
4271 if (config->sample_rate == 0)
4272 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4273 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4274 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4275 if (config->format == AUDIO_FORMAT_DEFAULT)
4276 config->format = AUDIO_FORMAT_PCM_16_BIT;
4277
4278 channels = audio_channel_count_from_out_mask(out->channel_mask);
4279
Ashish Jain83a6cc22016-06-28 14:34:17 +05304280 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4281 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004282 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4283 out->flags);
4284 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304285 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4286 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4287 out->config = pcm_config_low_latency;
4288 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4289 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4290 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304291 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4292 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4293 if (out->config.period_size <= 0) {
4294 ALOGE("Invalid configuration period size is not valid");
4295 ret = -EINVAL;
4296 goto error_open;
4297 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304298 } else {
4299 /* primary path is the default path selected if no other outputs are available/suitable */
4300 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4301 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4302 }
4303 out->hal_ip_format = format = out->format;
4304 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4305 out->hal_op_format = pcm_format_to_hal(out->config.format);
4306 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4307 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004308 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304309 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304310 if (out->hal_ip_format != out->hal_op_format) {
4311 uint32_t buffer_size = out->config.period_size *
4312 format_to_bitwidth_table[out->hal_op_format] *
4313 out->config.channels;
4314 out->convert_buffer = calloc(1, buffer_size);
4315 if (out->convert_buffer == NULL){
4316 ALOGE("Allocation failed for convert buffer for size %d",
4317 out->compr_config.fragment_size);
4318 ret = -ENOMEM;
4319 goto error_open;
4320 }
4321 ALOGD("Convert buffer allocated of size %d", buffer_size);
4322 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323 }
4324
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004325 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4326 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304327
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004328 /* TODO remove this hardcoding and check why width is zero*/
4329 if (out->bit_width == 0)
4330 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304331 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004332 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304333 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304334 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304335 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004336 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4337 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4338 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004339 if(adev->primary_output == NULL)
4340 adev->primary_output = out;
4341 else {
4342 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004343 ret = -EEXIST;
4344 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004345 }
4346 }
4347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004348 /* Check if this usecase is already existing */
4349 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004350 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4351 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004354 ret = -EEXIST;
4355 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 pthread_mutex_unlock(&adev->lock);
4359
4360 out->stream.common.get_sample_rate = out_get_sample_rate;
4361 out->stream.common.set_sample_rate = out_set_sample_rate;
4362 out->stream.common.get_buffer_size = out_get_buffer_size;
4363 out->stream.common.get_channels = out_get_channels;
4364 out->stream.common.get_format = out_get_format;
4365 out->stream.common.set_format = out_set_format;
4366 out->stream.common.standby = out_standby;
4367 out->stream.common.dump = out_dump;
4368 out->stream.common.set_parameters = out_set_parameters;
4369 out->stream.common.get_parameters = out_get_parameters;
4370 out->stream.common.add_audio_effect = out_add_audio_effect;
4371 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4372 out->stream.get_latency = out_get_latency;
4373 out->stream.set_volume = out_set_volume;
4374 out->stream.write = out_write;
4375 out->stream.get_render_position = out_get_render_position;
4376 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004377 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004379 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004381 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004382 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383
4384 config->format = out->stream.common.get_format(&out->stream.common);
4385 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4386 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4387
4388 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304389 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004390 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004391
4392 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4393 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4394 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004395 /* setup a channel for client <--> adsp communication for stream events */
4396 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
4397 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
4398 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4399 out->usecase, PCM_PLAYBACK);
4400 hdlr_stream_cfg.flags = out->flags;
4401 hdlr_stream_cfg.type = PCM_PLAYBACK;
4402 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4403 &hdlr_stream_cfg);
4404 if (ret) {
4405 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4406 out->adsp_hdlr_stream_handle = NULL;
4407 }
4408 }
Eric Laurent994a6932013-07-17 11:51:42 -07004409 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004410 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004411
4412error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304413 if (out->convert_buffer)
4414 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004415 free(out);
4416 *stream_out = NULL;
4417 ALOGD("%s: exit: ret %d", __func__, ret);
4418 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419}
4420
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304421void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 struct audio_stream_out *stream)
4423{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004424 struct stream_out *out = (struct stream_out *)stream;
4425 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004426 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004427
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304428 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4429
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004430 /* close adsp hdrl session before standby */
4431 if (out->adsp_hdlr_stream_handle) {
4432 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4433 if (ret)
4434 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4435 out->adsp_hdlr_stream_handle = NULL;
4436 }
4437
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004438 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304439 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004440 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304441 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004442 if(ret != 0)
4443 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4444 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004445 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004446 out_standby(&stream->common);
4447
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004448 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004449 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004450 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004451 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004452 if (out->compr_config.codec != NULL)
4453 free(out->compr_config.codec);
4454 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004455
Ashish Jain83a6cc22016-06-28 14:34:17 +05304456 if (out->convert_buffer != NULL) {
4457 free(out->convert_buffer);
4458 out->convert_buffer = NULL;
4459 }
4460
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004461 if (adev->voice_tx_output == out)
4462 adev->voice_tx_output = NULL;
4463
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304464 if (adev->primary_output == out)
4465 adev->primary_output = NULL;
4466
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004467 pthread_cond_destroy(&out->cond);
4468 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004470 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471}
4472
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004473static void close_compress_sessions(struct audio_device *adev)
4474{
Mingming Yin7b762e72015-03-04 13:47:32 -08004475 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304476 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004477 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004478 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304479
4480 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004481 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304482 if (is_offload_usecase(usecase->id)) {
4483 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004484 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4485 out = usecase->stream.out;
4486 pthread_mutex_unlock(&adev->lock);
4487 out_standby(&out->stream.common);
4488 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004489 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004490 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304491 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004492 }
4493 pthread_mutex_unlock(&adev->lock);
4494}
4495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004496static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4497{
4498 struct audio_device *adev = (struct audio_device *)dev;
4499 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004501 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004502 int ret;
4503 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004504
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004505 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004506 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004507
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304508 if (!parms)
4509 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004510 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4511 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304512 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304513 if (strstr(snd_card_status, "OFFLINE")) {
4514 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304515 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004516 //close compress sessions on OFFLINE status
4517 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304518 } else if (strstr(snd_card_status, "ONLINE")) {
4519 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304520 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004521 //send dts hpx license if enabled
4522 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304523 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304524 }
4525
4526 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004527 status = voice_set_parameters(adev, parms);
4528 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004529 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004530
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004531 status = platform_set_parameters(adev->platform, parms);
4532 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004533 goto done;
4534
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004535 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4536 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004537 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4539 adev->bluetooth_nrec = true;
4540 else
4541 adev->bluetooth_nrec = false;
4542 }
4543
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004544 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4545 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4547 adev->screen_off = false;
4548 else
4549 adev->screen_off = true;
4550 }
4551
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004552 ret = str_parms_get_int(parms, "rotation", &val);
4553 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004554 bool reverse_speakers = false;
4555 switch(val) {
4556 // FIXME: note that the code below assumes that the speakers are in the correct placement
4557 // relative to the user when the device is rotated 90deg from its default rotation. This
4558 // assumption is device-specific, not platform-specific like this code.
4559 case 270:
4560 reverse_speakers = true;
4561 break;
4562 case 0:
4563 case 90:
4564 case 180:
4565 break;
4566 default:
4567 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004568 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004569 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004570 if (status == 0) {
4571 if (adev->speaker_lr_swap != reverse_speakers) {
4572 adev->speaker_lr_swap = reverse_speakers;
4573 // only update the selected device if there is active pcm playback
4574 struct audio_usecase *usecase;
4575 struct listnode *node;
4576 list_for_each(node, &adev->usecase_list) {
4577 usecase = node_to_item(node, struct audio_usecase, list);
4578 if (usecase->type == PCM_PLAYBACK) {
4579 select_devices(adev, usecase->id);
4580 break;
4581 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004582 }
4583 }
4584 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004585 }
4586
Mingming Yin514a8bc2014-07-29 15:22:21 -07004587 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4588 if (ret >= 0) {
4589 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4590 adev->bt_wb_speech_enabled = true;
4591 else
4592 adev->bt_wb_speech_enabled = false;
4593 }
4594
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004595 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4596 if (ret >= 0) {
4597 val = atoi(value);
4598 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004599 ALOGV("cache new ext disp type and edid");
4600 ret = platform_get_ext_disp_type(adev->platform);
4601 if (ret < 0) {
4602 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004603 status = ret;
4604 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004605 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004606 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004607 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004608 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004609 /*
4610 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4611 * Per AudioPolicyManager, USB device is higher priority than WFD.
4612 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4613 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4614 * starting voice call on USB
4615 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004616 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4617 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004618 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4619 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004620 }
vivek mehta344576a2016-04-12 18:56:03 -07004621 ALOGV("detected USB connect .. disable proxy");
4622 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004623 }
4624 }
4625
4626 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4627 if (ret >= 0) {
4628 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004629 /*
4630 * The HDMI / Displayport disconnect handling has been moved to
4631 * audio extension to ensure that its parameters are not
4632 * invalidated prior to updating sysfs of the disconnect event
4633 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4634 */
4635 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004636 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004637 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4638 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304639 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4640 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004641 }
vivek mehta344576a2016-04-12 18:56:03 -07004642 ALOGV("detected USB disconnect .. enable proxy");
4643 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004644 }
4645 }
4646
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304647 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4648 if (ret >= 0) {
4649 struct audio_usecase *usecase;
4650 struct listnode *node;
4651 list_for_each(node, &adev->usecase_list) {
4652 usecase = node_to_item(node, struct audio_usecase, list);
4653 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004654 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304655 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304656 lock_output_stream(usecase->stream.out);
4657 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304658 //force device switch to re configure encoder
4659 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304660 audio_extn_a2dp_set_handoff_mode(false);
4661 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304662 break;
4663 }
4664 }
4665 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004666
4667 //handle vr audio setparam
4668 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4669 value, sizeof(value));
4670 if (ret >= 0) {
4671 ALOGI("Setting vr mode to be %s", value);
4672 if (!strncmp(value, "true", 4)) {
4673 adev->vr_audio_mode_enabled = true;
4674 ALOGI("Setting vr mode to true");
4675 } else if (!strncmp(value, "false", 5)) {
4676 adev->vr_audio_mode_enabled = false;
4677 ALOGI("Setting vr mode to false");
4678 } else {
4679 ALOGI("wrong vr mode set");
4680 }
4681 }
4682
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304683 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004684done:
4685 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004686 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304687error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004688 ALOGV("%s: exit with code(%d)", __func__, status);
4689 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690}
4691
4692static char* adev_get_parameters(const struct audio_hw_device *dev,
4693 const char *keys)
4694{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004695 struct audio_device *adev = (struct audio_device *)dev;
4696 struct str_parms *reply = str_parms_create();
4697 struct str_parms *query = str_parms_create_str(keys);
4698 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304699 char value[256] = {0};
4700 int ret = 0;
4701
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004702 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004703 if (reply) {
4704 str_parms_destroy(reply);
4705 }
4706 if (query) {
4707 str_parms_destroy(query);
4708 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004709 ALOGE("adev_get_parameters: failed to create query or reply");
4710 return NULL;
4711 }
4712
Naresh Tannirud7205b62014-06-20 02:54:48 +05304713 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4714 sizeof(value));
4715 if (ret >=0) {
4716 int val = 1;
4717 pthread_mutex_lock(&adev->snd_card_status.lock);
4718 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4719 val = 0;
4720 pthread_mutex_unlock(&adev->snd_card_status.lock);
4721 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4722 goto exit;
4723 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004724 //handle vr audio getparam
4725
4726 ret = str_parms_get_str(query,
4727 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4728 value, sizeof(value));
4729
4730 if (ret >= 0) {
4731 bool vr_audio_enabled = false;
4732 pthread_mutex_lock(&adev->lock);
4733 vr_audio_enabled = adev->vr_audio_mode_enabled;
4734 pthread_mutex_unlock(&adev->lock);
4735
4736 ALOGI("getting vr mode to %d", vr_audio_enabled);
4737
4738 if (vr_audio_enabled) {
4739 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4740 "true");
4741 goto exit;
4742 } else {
4743 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4744 "false");
4745 goto exit;
4746 }
4747 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004748
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004749 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004750 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004751 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004752 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304753 pthread_mutex_unlock(&adev->lock);
4754
Naresh Tannirud7205b62014-06-20 02:54:48 +05304755exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004756 str = str_parms_to_str(reply);
4757 str_parms_destroy(query);
4758 str_parms_destroy(reply);
4759
4760 ALOGV("%s: exit: returns - %s", __func__, str);
4761 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762}
4763
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004764static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765{
4766 return 0;
4767}
4768
4769static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4770{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004771 int ret;
4772 struct audio_device *adev = (struct audio_device *)dev;
4773 pthread_mutex_lock(&adev->lock);
4774 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004775 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004776 pthread_mutex_unlock(&adev->lock);
4777 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778}
4779
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004780static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4781 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004782{
4783 return -ENOSYS;
4784}
4785
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004786static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4787 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788{
4789 return -ENOSYS;
4790}
4791
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004792static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4793 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794{
4795 return -ENOSYS;
4796}
4797
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004798static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4799 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800{
4801 return -ENOSYS;
4802}
4803
4804static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4805{
4806 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004808 pthread_mutex_lock(&adev->lock);
4809 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004810 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004811 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004812 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004813 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004814 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004815 adev->current_call_output = NULL;
4816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 }
4818 pthread_mutex_unlock(&adev->lock);
4819 return 0;
4820}
4821
4822static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4823{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004824 int ret;
4825
4826 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004827 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004828 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4829 pthread_mutex_unlock(&adev->lock);
4830
4831 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004832}
4833
4834static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4835{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004836 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837 return 0;
4838}
4839
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004840static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841 const struct audio_config *config)
4842{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004843 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004845 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4846 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847}
4848
4849static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004850 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851 audio_devices_t devices,
4852 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004853 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304854 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004855 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004856 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857{
4858 struct audio_device *adev = (struct audio_device *)dev;
4859 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004860 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004861 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004862 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304863 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304866 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4867 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304869 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870
4871 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004872
4873 if (!in) {
4874 ALOGE("failed to allocate input stream");
4875 return -ENOMEM;
4876 }
4877
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304878 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304879 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4880 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004881 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004882 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884 in->stream.common.get_sample_rate = in_get_sample_rate;
4885 in->stream.common.set_sample_rate = in_set_sample_rate;
4886 in->stream.common.get_buffer_size = in_get_buffer_size;
4887 in->stream.common.get_channels = in_get_channels;
4888 in->stream.common.get_format = in_get_format;
4889 in->stream.common.set_format = in_set_format;
4890 in->stream.common.standby = in_standby;
4891 in->stream.common.dump = in_dump;
4892 in->stream.common.set_parameters = in_set_parameters;
4893 in->stream.common.get_parameters = in_get_parameters;
4894 in->stream.common.add_audio_effect = in_add_audio_effect;
4895 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4896 in->stream.set_gain = in_set_gain;
4897 in->stream.read = in_read;
4898 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4899
4900 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004901 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903 in->standby = 1;
4904 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004905 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004906 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304908 in->usecase = USECASE_AUDIO_RECORD;
4909 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4910 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4911 is_low_latency = true;
4912#if LOW_LATENCY_CAPTURE_USE_CASE
4913 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4914#endif
4915 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4916 }
4917
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004918 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004919 if (in->realtime) {
4920 in->config = pcm_config_audio_capture_rt;
4921 in->sample_rate = in->config.rate;
4922 in->af_period_multiplier = af_period_multiplier;
4923 } else {
4924 in->config = pcm_config_audio_capture;
4925 in->config.rate = config->sample_rate;
4926 in->sample_rate = config->sample_rate;
4927 in->af_period_multiplier = 1;
4928 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304929 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304931 /* restrict 24 bit capture for unprocessed source only
4932 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4933 */
4934 if (config->format == AUDIO_FORMAT_DEFAULT) {
4935 config->format = AUDIO_FORMAT_PCM_16_BIT;
4936 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4937 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4938 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4939 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4940 bool ret_error = false;
4941 in->bit_width = 24;
4942 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4943 from HAL is 24_packed and 8_24
4944 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4945 24_packed return error indicating supported format is 24_packed
4946 *> In case of any other source requesting 24 bit or float return error
4947 indicating format supported is 16 bit only.
4948
4949 on error flinger will retry with supported format passed
4950 */
4951 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4952 (source != AUDIO_SOURCE_CAMCORDER)) {
4953 config->format = AUDIO_FORMAT_PCM_16_BIT;
4954 if (config->sample_rate > 48000)
4955 config->sample_rate = 48000;
4956 ret_error = true;
4957 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4958 in->config.format = PCM_FORMAT_S24_3LE;
4959 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4960 in->config.format = PCM_FORMAT_S24_LE;
4961 } else {
4962 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4963 ret_error = true;
4964 }
4965
4966 if (ret_error) {
4967 ret = -EINVAL;
4968 goto err_open;
4969 }
4970 }
4971
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304972 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304973 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4974 (adev->mode != AUDIO_MODE_IN_CALL)) {
4975 ret = -EINVAL;
4976 goto err_open;
4977 }
4978
4979 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4980 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004981 if (config->sample_rate == 0)
4982 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4983 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4984 config->sample_rate != 8000) {
4985 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4986 ret = -EINVAL;
4987 goto err_open;
4988 }
4989 if (config->format == AUDIO_FORMAT_DEFAULT)
4990 config->format = AUDIO_FORMAT_PCM_16_BIT;
4991 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4992 config->format = AUDIO_FORMAT_PCM_16_BIT;
4993 ret = -EINVAL;
4994 goto err_open;
4995 }
4996
4997 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4998 in->config = pcm_config_afe_proxy_record;
4999 in->config.channels = channel_count;
5000 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305001 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305002 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5003 in, config, &channel_mask_updated)) {
5004 if (channel_mask_updated == true) {
5005 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5006 __func__, config->channel_mask);
5007 ret = -EINVAL;
5008 goto err_open;
5009 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305010 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005011 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005012 audio_extn_compr_cap_format_supported(config->format) &&
5013 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005014 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305015 } else if (audio_extn_cin_applicable_stream(in)) {
5016 ret = audio_extn_cin_configure_input_stream(in);
5017 if (ret)
5018 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005019 } else {
5020 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005021 if (!in->realtime) {
5022 in->format = config->format;
5023 frame_size = audio_stream_in_frame_size(&in->stream);
5024 buffer_size = get_input_buffer_size(config->sample_rate,
5025 config->format,
5026 channel_count,
5027 is_low_latency);
5028 in->config.period_size = buffer_size / frame_size;
5029 }
5030
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005031 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005032 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005033 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005034 (in->config.rate == 8000 || in->config.rate == 16000 ||
5035 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005036 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5037 voice_extn_compress_voip_open_input_stream(in);
5038 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305041 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5042 &adev->streams_input_cfg_list,
5043 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305044 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305045
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005046 /* This stream could be for sound trigger lab,
5047 get sound trigger pcm if present */
5048 audio_extn_sound_trigger_check_and_get_session(in);
5049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005050 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005051 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005052 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005053
5054err_open:
5055 free(in);
5056 *stream_in = NULL;
5057 return ret;
5058}
5059
5060static void adev_close_input_stream(struct audio_hw_device *dev,
5061 struct audio_stream_in *stream)
5062{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005063 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005064 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005065 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305066
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305067 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005068
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305069 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005070 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305071
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005072 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305073 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005074 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305075 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005076 if (ret != 0)
5077 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5078 __func__, ret);
5079 } else
5080 in_standby(&stream->common);
5081
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005082 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005083 audio_extn_ssr_deinit();
5084 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005085
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305086 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005087 audio_extn_compr_cap_format_supported(in->config.format))
5088 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305089
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305090 if (audio_extn_cin_attached_usecase(in->usecase))
5091 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005092
Mingming Yinfd7607b2016-01-22 12:48:44 -08005093 if (in->is_st_session) {
5094 ALOGV("%s: sound trigger pcm stop lab", __func__);
5095 audio_extn_sound_trigger_stop_lab(in);
5096 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005097 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 return;
5099}
5100
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005101static int adev_dump(const audio_hw_device_t *device __unused,
5102 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005103{
5104 return 0;
5105}
5106
5107static int adev_close(hw_device_t *device)
5108{
5109 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005110
5111 if (!adev)
5112 return 0;
5113
5114 pthread_mutex_lock(&adev_init_lock);
5115
5116 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005117 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005118 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305119 audio_extn_utils_release_streams_cfg_lists(
5120 &adev->streams_output_cfg_list,
5121 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305122 if (audio_extn_qaf_is_enabled())
5123 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005124 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005125 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005126 free(adev->snd_dev_ref_cnt);
5127 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005128 if (adev->adm_deinit)
5129 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305130 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005131 audio_extn_adsp_hdlr_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005132 free(device);
5133 adev = NULL;
5134 }
5135 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137 return 0;
5138}
5139
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005140/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5141 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5142 * just that it _might_ work.
5143 */
5144static int period_size_is_plausible_for_low_latency(int period_size)
5145{
5146 switch (period_size) {
5147 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005148 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005149 case 240:
5150 case 320:
5151 case 480:
5152 return 1;
5153 default:
5154 return 0;
5155 }
5156}
5157
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158static int adev_open(const hw_module_t *module, const char *name,
5159 hw_device_t **device)
5160{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305161 int ret;
5162
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005163 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5165
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005166 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005167 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005168 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005169 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005170 ALOGD("%s: returning existing instance of adev", __func__);
5171 ALOGD("%s: exit", __func__);
5172 pthread_mutex_unlock(&adev_init_lock);
5173 return 0;
5174 }
5175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005176 adev = calloc(1, sizeof(struct audio_device));
5177
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005178 if (!adev) {
5179 pthread_mutex_unlock(&adev_init_lock);
5180 return -ENOMEM;
5181 }
5182
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005183 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5184
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305185#ifdef DYNAMIC_LOG_ENABLED
5186 register_for_dynamic_logging("hal");
5187#endif
5188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005189 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5190 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5191 adev->device.common.module = (struct hw_module_t *)module;
5192 adev->device.common.close = adev_close;
5193
5194 adev->device.init_check = adev_init_check;
5195 adev->device.set_voice_volume = adev_set_voice_volume;
5196 adev->device.set_master_volume = adev_set_master_volume;
5197 adev->device.get_master_volume = adev_get_master_volume;
5198 adev->device.set_master_mute = adev_set_master_mute;
5199 adev->device.get_master_mute = adev_get_master_mute;
5200 adev->device.set_mode = adev_set_mode;
5201 adev->device.set_mic_mute = adev_set_mic_mute;
5202 adev->device.get_mic_mute = adev_get_mic_mute;
5203 adev->device.set_parameters = adev_set_parameters;
5204 adev->device.get_parameters = adev_get_parameters;
5205 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5206 adev->device.open_output_stream = adev_open_output_stream;
5207 adev->device.close_output_stream = adev_close_output_stream;
5208 adev->device.open_input_stream = adev_open_input_stream;
5209 adev->device.close_input_stream = adev_close_input_stream;
5210 adev->device.dump = adev_dump;
5211
5212 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005214 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005215 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005216 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005217 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005218 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005219 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005220 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005221 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005222 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005223 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005224 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005225 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305226 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305227 adev->perf_lock_opts[0] = 0x101;
5228 adev->perf_lock_opts[1] = 0x20E;
5229 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305230
5231 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5232 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005233 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005234 adev->platform = platform_init(adev);
5235 if (!adev->platform) {
5236 free(adev->snd_dev_ref_cnt);
5237 free(adev);
5238 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5239 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005240 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305241 pthread_mutex_destroy(&adev->lock);
5242 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005243 return -EINVAL;
5244 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005245
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305246 if (audio_extn_qaf_is_enabled()) {
5247 ret = audio_extn_qaf_init(adev);
5248 if (ret < 0) {
5249 free(adev);
5250 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5251 *device = NULL;
5252 pthread_mutex_unlock(&adev_init_lock);
5253 pthread_mutex_destroy(&adev->lock);
5254 return ret;
5255 }
5256
5257 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5258 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5259 }
5260
Naresh Tanniru4c630392014-05-12 01:05:52 +05305261 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5262
Eric Laurentc4aef752013-09-12 17:45:53 -07005263 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5264 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5265 if (adev->visualizer_lib == NULL) {
5266 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5267 } else {
5268 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5269 adev->visualizer_start_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_start_output");
5272 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005273 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005274 "visualizer_hal_stop_output");
5275 }
5276 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305277 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005278 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005279 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005280 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005281
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005282 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5283 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5284 if (adev->offload_effects_lib == NULL) {
5285 ALOGE("%s: DLOPEN failed for %s", __func__,
5286 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5287 } else {
5288 ALOGV("%s: DLOPEN successful for %s", __func__,
5289 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5290 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305291 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005292 "offload_effects_bundle_hal_start_output");
5293 adev->offload_effects_stop_output =
5294 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5295 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005296 adev->offload_effects_set_hpx_state =
5297 (int (*)(bool))dlsym(adev->offload_effects_lib,
5298 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305299 adev->offload_effects_get_parameters =
5300 (void (*)(struct str_parms *, struct str_parms *))
5301 dlsym(adev->offload_effects_lib,
5302 "offload_effects_bundle_get_parameters");
5303 adev->offload_effects_set_parameters =
5304 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5305 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005306 }
5307 }
5308
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005309 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5310 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5311 if (adev->adm_lib == NULL) {
5312 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5313 } else {
5314 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5315 adev->adm_init = (adm_init_t)
5316 dlsym(adev->adm_lib, "adm_init");
5317 adev->adm_deinit = (adm_deinit_t)
5318 dlsym(adev->adm_lib, "adm_deinit");
5319 adev->adm_register_input_stream = (adm_register_input_stream_t)
5320 dlsym(adev->adm_lib, "adm_register_input_stream");
5321 adev->adm_register_output_stream = (adm_register_output_stream_t)
5322 dlsym(adev->adm_lib, "adm_register_output_stream");
5323 adev->adm_deregister_stream = (adm_deregister_stream_t)
5324 dlsym(adev->adm_lib, "adm_deregister_stream");
5325 adev->adm_request_focus = (adm_request_focus_t)
5326 dlsym(adev->adm_lib, "adm_request_focus");
5327 adev->adm_abandon_focus = (adm_abandon_focus_t)
5328 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005329 adev->adm_set_config = (adm_set_config_t)
5330 dlsym(adev->adm_lib, "adm_set_config");
5331 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5332 dlsym(adev->adm_lib, "adm_request_focus_v2");
5333 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5334 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5335 adev->adm_on_routing_change = (adm_on_routing_change_t)
5336 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005337 }
5338 }
5339
Mingming Yin514a8bc2014-07-29 15:22:21 -07005340 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005341 //initialize this to false for now,
5342 //this will be set to true through set param
5343 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005344
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005345 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346 *device = &adev->device.common;
5347
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305348 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5349 &adev->streams_output_cfg_list,
5350 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005351
Kiran Kandi910e1862013-10-29 13:29:42 -07005352 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005353
5354 char value[PROPERTY_VALUE_MAX];
5355 int trial;
5356 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5357 trial = atoi(value);
5358 if (period_size_is_plausible_for_low_latency(trial)) {
5359 pcm_config_low_latency.period_size = trial;
5360 pcm_config_low_latency.start_threshold = trial / 4;
5361 pcm_config_low_latency.avail_min = trial / 4;
5362 configured_low_latency_capture_period_size = trial;
5363 }
5364 }
5365 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5366 trial = atoi(value);
5367 if (period_size_is_plausible_for_low_latency(trial)) {
5368 configured_low_latency_capture_period_size = trial;
5369 }
5370 }
5371
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005372 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5373 af_period_multiplier = atoi(value);
5374 if (af_period_multiplier < 0)
5375 af_period_multiplier = 2;
5376 else if (af_period_multiplier > 4)
5377 af_period_multiplier = 4;
5378
5379 ALOGV("new period_multiplier = %d", af_period_multiplier);
5380 }
5381
vivek mehta446c3962015-09-14 10:57:35 -07005382 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005383 pthread_mutex_unlock(&adev_init_lock);
5384
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005385 if (adev->adm_init)
5386 adev->adm_data = adev->adm_init();
5387
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305388 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305389 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005390 audio_extn_adsp_hdlr_init(adev->mixer);
Eric Laurent994a6932013-07-17 11:51:42 -07005391 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005392 return 0;
5393}
5394
5395static struct hw_module_methods_t hal_module_methods = {
5396 .open = adev_open,
5397};
5398
5399struct audio_module HAL_MODULE_INFO_SYM = {
5400 .common = {
5401 .tag = HARDWARE_MODULE_TAG,
5402 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5403 .hal_api_version = HARDWARE_HAL_API_VERSION,
5404 .id = AUDIO_HARDWARE_MODULE_ID,
5405 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005406 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005407 .methods = &hal_module_methods,
5408 },
5409};