blob: 68f59788b406cdfb786bc3258dad450d41fb816d [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),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700305 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800306};
307
308//list of all supported sample rates by HDMI specification.
309static const int out_hdmi_sample_rates[] = {
310 32000, 44100, 48000, 88200, 96000, 176400, 192000,
311};
312
313static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
314 STRING_TO_ENUM(32000),
315 STRING_TO_ENUM(44100),
316 STRING_TO_ENUM(48000),
317 STRING_TO_ENUM(88200),
318 STRING_TO_ENUM(96000),
319 STRING_TO_ENUM(176400),
320 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700321};
322
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700323static struct audio_device *adev = NULL;
324static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700325static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700326//cache last MBDRC cal step level
327static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700328
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700329static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
330 int flags __unused)
331{
332 int dir = 0;
333 switch (uc_id) {
334 case USECASE_AUDIO_RECORD_LOW_LATENCY:
335 dir = 1;
336 case USECASE_AUDIO_PLAYBACK_ULL:
337 break;
338 default:
339 return false;
340 }
341
342 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
343 PCM_PLAYBACK : PCM_CAPTURE);
344 if (adev->adm_is_noirq_avail)
345 return adev->adm_is_noirq_avail(adev->adm_data,
346 adev->snd_card, dev_id, dir);
347 return false;
348}
349
350static void register_out_stream(struct stream_out *out)
351{
352 struct audio_device *adev = out->dev;
353 if (is_offload_usecase(out->usecase) ||
354 !adev->adm_register_output_stream)
355 return;
356
357 // register stream first for backward compatibility
358 adev->adm_register_output_stream(adev->adm_data,
359 out->handle,
360 out->flags);
361
362 if (!adev->adm_set_config)
363 return;
364
365 if (out->realtime)
366 adev->adm_set_config(adev->adm_data,
367 out->handle,
368 out->pcm, &out->config);
369}
370
371static void register_in_stream(struct stream_in *in)
372{
373 struct audio_device *adev = in->dev;
374 if (!adev->adm_register_input_stream)
375 return;
376
377 adev->adm_register_input_stream(adev->adm_data,
378 in->capture_handle,
379 in->flags);
380
381 if (!adev->adm_set_config)
382 return;
383
384 if (in->realtime)
385 adev->adm_set_config(adev->adm_data,
386 in->capture_handle,
387 in->pcm,
388 &in->config);
389}
390
391static void request_out_focus(struct stream_out *out, long ns)
392{
393 struct audio_device *adev = out->dev;
394
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700395 if (adev->adm_request_focus_v2)
396 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
397 else if (adev->adm_request_focus)
398 adev->adm_request_focus(adev->adm_data, out->handle);
399}
400
401static void request_in_focus(struct stream_in *in, long ns)
402{
403 struct audio_device *adev = in->dev;
404
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700405 if (adev->adm_request_focus_v2)
406 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
407 else if (adev->adm_request_focus)
408 adev->adm_request_focus(adev->adm_data, in->capture_handle);
409}
410
411static void release_out_focus(struct stream_out *out)
412{
413 struct audio_device *adev = out->dev;
414
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, out->handle);
417}
418
419static void release_in_focus(struct stream_in *in)
420{
421 struct audio_device *adev = in->dev;
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
424}
425
vivek mehtaa76401a2015-04-24 14:12:15 -0700426__attribute__ ((visibility ("default")))
427bool audio_hw_send_gain_dep_calibration(int level) {
428 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700429 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700430
431 pthread_mutex_lock(&adev_init_lock);
432
433 if (adev != NULL && adev->platform != NULL) {
434 pthread_mutex_lock(&adev->lock);
435 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700436
437 // if cal set fails, cache level info
438 // if cal set succeds, reset known last cal set
439 if (!ret_val)
440 last_known_cal_step = level;
441 else if (last_known_cal_step != -1)
442 last_known_cal_step = -1;
443
vivek mehtaa76401a2015-04-24 14:12:15 -0700444 pthread_mutex_unlock(&adev->lock);
445 } else {
446 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
447 }
448
449 pthread_mutex_unlock(&adev_init_lock);
450
451 return ret_val;
452}
453
Ashish Jain5106d362016-05-11 19:23:33 +0530454static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
455{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800456 bool gapless_enabled = false;
457 const char *mixer_ctl_name = "Compress Gapless Playback";
458 struct mixer_ctl *ctl;
459
460 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530461 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
462
463 /*Disable gapless if its AV playback*/
464 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800465
466 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
467 if (!ctl) {
468 ALOGE("%s: Could not get ctl for mixer cmd - %s",
469 __func__, mixer_ctl_name);
470 return -EINVAL;
471 }
472
473 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
474 ALOGE("%s: Could not set gapless mode %d",
475 __func__, gapless_enabled);
476 return -EINVAL;
477 }
478 return 0;
479}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700480
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700481__attribute__ ((visibility ("default")))
482int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
483 int table_size) {
484 int ret_val = 0;
485 ALOGV("%s: enter ... ", __func__);
486
487 pthread_mutex_lock(&adev_init_lock);
488 if (adev == NULL) {
489 ALOGW("%s: adev is NULL .... ", __func__);
490 goto done;
491 }
492
493 pthread_mutex_lock(&adev->lock);
494 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
495 pthread_mutex_unlock(&adev->lock);
496done:
497 pthread_mutex_unlock(&adev_init_lock);
498 ALOGV("%s: exit ... ", __func__);
499 return ret_val;
500}
501
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700502static bool is_supported_format(audio_format_t format)
503{
Eric Laurent86e17132013-09-12 17:49:30 -0700504 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530505 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530506 format == AUDIO_FORMAT_AAC_LC ||
507 format == AUDIO_FORMAT_AAC_HE_V1 ||
508 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530509 format == AUDIO_FORMAT_AAC_ADTS_LC ||
510 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
511 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530512 format == AUDIO_FORMAT_AAC_LATM_LC ||
513 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
514 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530515 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
516 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530517 format == AUDIO_FORMAT_PCM_FLOAT ||
518 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700519 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530520 format == AUDIO_FORMAT_AC3 ||
521 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700522 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530523 format == AUDIO_FORMAT_DTS ||
524 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800525 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530526 format == AUDIO_FORMAT_ALAC ||
527 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530528 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530529 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800530 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530531 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700532 format == AUDIO_FORMAT_APTX ||
533 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800534 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700535
536 return false;
537}
538
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700539static inline bool is_mmap_usecase(audio_usecase_t uc_id)
540{
541 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
542 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
543}
544
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530545int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530546{
547 int snd_scard_state;
548
549 if (!adev)
550 return SND_CARD_STATE_OFFLINE;
551
552 pthread_mutex_lock(&adev->snd_card_status.lock);
553 snd_scard_state = adev->snd_card_status.state;
554 pthread_mutex_unlock(&adev->snd_card_status.lock);
555
556 return snd_scard_state;
557}
558
559static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
560{
561 if (!adev)
562 return -ENOSYS;
563
564 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700565 if (adev->snd_card_status.state != snd_scard_state) {
566 adev->snd_card_status.state = snd_scard_state;
567 platform_snd_card_update(adev->platform, snd_scard_state);
568 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530569 pthread_mutex_unlock(&adev->snd_card_status.lock);
570
571 return 0;
572}
573
Avinash Vaish71a8b972014-07-24 15:36:33 +0530574static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
575 struct audio_usecase *uc_info)
576{
577 struct listnode *node;
578 struct audio_usecase *usecase;
579
580 if (uc_info == NULL)
581 return -EINVAL;
582
583 /* Re-route all voice usecases on the shared backend other than the
584 specified usecase to new snd devices */
585 list_for_each(node, &adev->usecase_list) {
586 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800587 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530588 enable_audio_route(adev, usecase);
589 }
590 return 0;
591}
592
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530593static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530594{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530595 ALOGV("%s", __func__);
596 audio_route_apply_and_update_path(adev->audio_route,
597 "asrc-mode");
598 adev->asrc_mode_enabled = true;
599}
600
601static void disable_asrc_mode(struct audio_device *adev)
602{
603 ALOGV("%s", __func__);
604 audio_route_reset_and_update_path(adev->audio_route,
605 "asrc-mode");
606 adev->asrc_mode_enabled = false;
607}
608
609/*
610 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
611 * 44.1 or Native DSD backends are enabled for any of current use case.
612 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
613 * - Disable current mix path use case(Headphone backend) and re-enable it with
614 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
615 * e.g. Naitve DSD or Headphone 44.1 -> + 48
616 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530617static void check_and_set_asrc_mode(struct audio_device *adev,
618 struct audio_usecase *uc_info,
619 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530620{
621 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530622 int i, num_new_devices = 0;
623 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
624 /*
625 *Split snd device for new combo use case
626 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
627 */
628 if (platform_split_snd_device(adev->platform,
629 snd_device,
630 &num_new_devices,
631 split_new_snd_devices) == 0) {
632 for (i = 0; i < num_new_devices; i++)
633 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
634 } else {
635 int new_backend_idx = platform_get_backend_index(snd_device);
636 if (((new_backend_idx == HEADPHONE_BACKEND) ||
637 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
638 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
639 !adev->asrc_mode_enabled) {
640 struct listnode *node = NULL;
641 struct audio_usecase *uc = NULL;
642 struct stream_out *curr_out = NULL;
643 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
644 int i, num_devices, ret = 0;
645 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530646
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530647 list_for_each(node, &adev->usecase_list) {
648 uc = node_to_item(node, struct audio_usecase, list);
649 curr_out = (struct stream_out*) uc->stream.out;
650 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
651 /*
652 *Split snd device for existing combo use case
653 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
654 */
655 ret = platform_split_snd_device(adev->platform,
656 uc->out_snd_device,
657 &num_devices,
658 split_snd_devices);
659 if (ret < 0 || num_devices == 0) {
660 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
661 split_snd_devices[0] = uc->out_snd_device;
662 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800663 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530664 for (i = 0; i < num_devices; i++) {
665 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
666 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
667 if((new_backend_idx == HEADPHONE_BACKEND) &&
668 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
669 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
670 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
671 __func__);
672 enable_asrc_mode(adev);
673 break;
674 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
675 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
676 (usecase_backend_idx == HEADPHONE_BACKEND)) {
677 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
678 __func__);
679 disable_audio_route(adev, uc);
680 disable_snd_device(adev, uc->out_snd_device);
681 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
682 if (new_backend_idx == DSD_NATIVE_BACKEND)
683 audio_route_apply_and_update_path(adev->audio_route,
684 "hph-true-highquality-mode");
685 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
686 (curr_out->bit_width >= 24))
687 audio_route_apply_and_update_path(adev->audio_route,
688 "hph-highquality-mode");
689 enable_asrc_mode(adev);
690 enable_snd_device(adev, uc->out_snd_device);
691 enable_audio_route(adev, uc);
692 break;
693 }
694 }
695 // reset split devices count
696 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800697 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530698 if (adev->asrc_mode_enabled)
699 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530700 }
701 }
702 }
703}
704
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700705int pcm_ioctl(struct pcm *pcm, int request, ...)
706{
707 va_list ap;
708 void * arg;
709 int pcm_fd = *(int*)pcm;
710
711 va_start(ap, request);
712 arg = va_arg(ap, void *);
713 va_end(ap);
714
715 return ioctl(pcm_fd, request, arg);
716}
717
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700718int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700719 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700722 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530723 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800724
725 if (usecase == NULL)
726 return -EINVAL;
727
728 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
729
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800730 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700731 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800732 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700733 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800734
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800735#ifdef DS1_DOLBY_DAP_ENABLED
736 audio_extn_dolby_set_dmid(adev);
737 audio_extn_dolby_set_endpoint(adev);
738#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700739 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700740 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530741 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700742 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530743 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530744 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
745 out = usecase->stream.out;
746 if (out && out->compr)
747 audio_extn_utils_compress_set_clk_rec_mode(usecase);
748 }
749
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800750 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700751 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700752 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700753 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754 ALOGV("%s: exit", __func__);
755 return 0;
756}
757
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700758int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700759 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700761 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700762 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800763
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530764 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800765 return -EINVAL;
766
767 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700768 if (usecase->type == PCM_CAPTURE)
769 snd_device = usecase->in_snd_device;
770 else
771 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800772 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700773 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700774 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700775 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700776 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530777 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800778 ALOGV("%s: exit", __func__);
779 return 0;
780}
781
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700782int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700783 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800784{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530785 int i, num_devices = 0;
786 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700787 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
788
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800789 if (snd_device < SND_DEVICE_MIN ||
790 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800791 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800792 return -EINVAL;
793 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700794
795 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700796
797 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
798 ALOGE("%s: Invalid sound device returned", __func__);
799 return -EINVAL;
800 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700801 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700802 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700803 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700804 return 0;
805 }
806
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530807
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700808 if (audio_extn_spkr_prot_is_enabled())
809 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700810
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800811 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
812 audio_extn_spkr_prot_is_enabled()) {
813 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700814 adev->snd_dev_ref_cnt[snd_device]--;
815 return -EINVAL;
816 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200817 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800818 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800819 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200820 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800821 return -EINVAL;
822 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700823 } else if (platform_split_snd_device(adev->platform,
824 snd_device,
825 &num_devices,
826 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530827 for (i = 0; i < num_devices; i++) {
828 enable_snd_device(adev, new_snd_devices[i]);
829 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800830 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700831 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530832
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530833
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530834 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
835 (audio_extn_a2dp_start_playback() < 0)) {
836 ALOGE(" fail to configure A2dp control path ");
837 return -EINVAL;
838 }
839
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700840 /* due to the possibility of calibration overwrite between listen
841 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700842 audio_extn_sound_trigger_update_device_status(snd_device,
843 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530844 audio_extn_listen_update_device_status(snd_device,
845 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700846 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700847 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700848 audio_extn_sound_trigger_update_device_status(snd_device,
849 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530850 audio_extn_listen_update_device_status(snd_device,
851 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700852 return -EINVAL;
853 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300854 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700855 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530856
857 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
858 !adev->native_playback_enabled &&
859 audio_is_true_native_stream_active(adev)) {
860 ALOGD("%s: %d: napb: enabling native mode in hardware",
861 __func__, __LINE__);
862 audio_route_apply_and_update_path(adev->audio_route,
863 "true-native-mode");
864 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800866 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800867 return 0;
868}
869
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700870int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700871 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800872{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530873 int i, num_devices = 0;
874 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700875 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
876
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800877 if (snd_device < SND_DEVICE_MIN ||
878 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800879 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800880 return -EINVAL;
881 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
883 ALOGE("%s: device ref cnt is already 0", __func__);
884 return -EINVAL;
885 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700886
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700888
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700889 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
890 ALOGE("%s: Invalid sound device returned", __func__);
891 return -EINVAL;
892 }
893
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700895 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530896
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800897 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
898 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700899 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700900 } else if (platform_split_snd_device(adev->platform,
901 snd_device,
902 &num_devices,
903 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530904 for (i = 0; i < num_devices; i++) {
905 disable_snd_device(adev, new_snd_devices[i]);
906 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300907 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700908 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300909 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700910
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530911 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
912 audio_extn_a2dp_stop_playback();
913
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700914 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530915 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530916 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
917 adev->native_playback_enabled) {
918 ALOGD("%s: %d: napb: disabling native mode in hardware",
919 __func__, __LINE__);
920 audio_route_reset_and_update_path(adev->audio_route,
921 "true-native-mode");
922 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530923 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
924 adev->asrc_mode_enabled) {
925 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530926 disable_asrc_mode(adev);
927 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530928 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530929
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200930 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700931 audio_extn_sound_trigger_update_device_status(snd_device,
932 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530933 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800934 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700935 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700936
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937 return 0;
938}
939
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700940/*
941 legend:
942 uc - existing usecase
943 new_uc - new usecase
944 d1, d11, d2 - SND_DEVICE enums
945 a1, a2 - corresponding ANDROID device enums
946 B1, B2 - backend strings
947
948case 1
949 uc->dev d1 (a1) B1
950 new_uc->dev d1 (a1), d2 (a2) B1, B2
951
952 resolution: disable and enable uc->dev on d1
953
954case 2
955 uc->dev d1 (a1) B1
956 new_uc->dev d11 (a1) B1
957
958 resolution: need to switch uc since d1 and d11 are related
959 (e.g. speaker and voice-speaker)
960 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
961
962case 3
963 uc->dev d1 (a1) B1
964 new_uc->dev d2 (a2) B2
965
966 resolution: no need to switch uc
967
968case 4
969 uc->dev d1 (a1) B1
970 new_uc->dev d2 (a2) B1
971
972 resolution: disable enable uc-dev on d2 since backends match
973 we cannot enable two streams on two different devices if they
974 share the same backend. e.g. if offload is on speaker device using
975 QUAD_MI2S backend and a low-latency stream is started on voice-handset
976 using the same backend, offload must also be switched to voice-handset.
977
978case 5
979 uc->dev d1 (a1) B1
980 new_uc->dev d1 (a1), d2 (a2) B1
981
982 resolution: disable enable uc-dev on d2 since backends match
983 we cannot enable two streams on two different devices if they
984 share the same backend.
985
986case 6
987 uc->dev d1 (a1) B1
988 new_uc->dev d2 (a1) B2
989
990 resolution: no need to switch
991
992case 7
993 uc->dev d1 (a1), d2 (a2) B1, B2
994 new_uc->dev d1 (a1) B1
995
996 resolution: no need to switch
997
998*/
999static snd_device_t derive_playback_snd_device(void * platform,
1000 struct audio_usecase *uc,
1001 struct audio_usecase *new_uc,
1002 snd_device_t new_snd_device)
1003{
1004 audio_devices_t a1 = uc->stream.out->devices;
1005 audio_devices_t a2 = new_uc->stream.out->devices;
1006
1007 snd_device_t d1 = uc->out_snd_device;
1008 snd_device_t d2 = new_snd_device;
1009
1010 // Treat as a special case when a1 and a2 are not disjoint
1011 if ((a1 != a2) && (a1 & a2)) {
1012 snd_device_t d3[2];
1013 int num_devices = 0;
1014 int ret = platform_split_snd_device(platform,
1015 popcount(a1) > 1 ? d1 : d2,
1016 &num_devices,
1017 d3);
1018 if (ret < 0) {
1019 if (ret != -ENOSYS) {
1020 ALOGW("%s failed to split snd_device %d",
1021 __func__,
1022 popcount(a1) > 1 ? d1 : d2);
1023 }
1024 goto end;
1025 }
1026
1027 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1028 // But if it does happen, we need to give priority to d2 if
1029 // the combo devices active on the existing usecase share a backend.
1030 // This is because we cannot have a usecase active on a combo device
1031 // and a new usecase requests one device in this combo pair.
1032 if (platform_check_backends_match(d3[0], d3[1])) {
1033 return d2; // case 5
1034 } else {
1035 return d1; // case 1
1036 }
1037 } else {
1038 if (platform_check_backends_match(d1, d2)) {
1039 return d2; // case 2, 4
1040 } else {
1041 return d1; // case 6, 3
1042 }
1043 }
1044
1045end:
1046 return d2; // return whatever was calculated before.
1047}
1048
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301050 struct audio_usecase *uc_info,
1051 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052{
1053 struct listnode *node;
1054 struct audio_usecase *usecase;
1055 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301056 snd_device_t uc_derive_snd_device;
1057 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001059 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301060 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001061 /*
1062 * This function is to make sure that all the usecases that are active on
1063 * the hardware codec backend are always routed to any one device that is
1064 * handled by the hardware codec.
1065 * For example, if low-latency and deep-buffer usecases are currently active
1066 * on speaker and out_set_parameters(headset) is received on low-latency
1067 * output, then we have to make sure deep-buffer is also switched to headset,
1068 * because of the limitation that both the devices cannot be enabled
1069 * at the same time as they share the same backend.
1070 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001071 /*
1072 * This call is to check if we need to force routing for a particular stream
1073 * If there is a backend configuration change for the device when a
1074 * new stream starts, then ADM needs to be closed and re-opened with the new
1075 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001076 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001077 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001078 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1079 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301080 /* For a2dp device reconfigure all active sessions
1081 * with new AFE encoder format based on a2dp state
1082 */
1083 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1084 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1085 audio_extn_a2dp_is_force_device_switch()) {
1086 force_routing = true;
1087 force_restart_session = true;
1088 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301089 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1090
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001092 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001093 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1095 switch_device[i] = false;
1096
1097 list_for_each(node, &adev->usecase_list) {
1098 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001099
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301100 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1101 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301102 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301103 platform_get_snd_device_name(usecase->out_snd_device),
1104 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301105 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1106 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1107 usecase, uc_info, snd_device);
1108 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1109 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1110 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1111 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
1112 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1113 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1114 ((force_restart_session) ||
1115 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301116 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1117 __func__, use_case_table[usecase->id],
1118 platform_get_snd_device_name(usecase->out_snd_device));
1119 disable_audio_route(adev, usecase);
1120 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301121 /* Enable existing usecase on derived playback device */
1122 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301123 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301124 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 }
1126 }
1127
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301128 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1129 num_uc_to_switch);
1130
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001132 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301134 /* Make sure the previous devices to be disabled first and then enable the
1135 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 list_for_each(node, &adev->usecase_list) {
1137 usecase = node_to_item(node, struct audio_usecase, list);
1138 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001139 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 }
1141 }
1142
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001143 list_for_each(node, &adev->usecase_list) {
1144 usecase = node_to_item(node, struct audio_usecase, list);
1145 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301146 enable_snd_device(adev, derive_snd_device[usecase->id]);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001147 }
1148 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 /* Re-route all the usecases on the shared backend other than the
1151 specified usecase to new snd devices */
1152 list_for_each(node, &adev->usecase_list) {
1153 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301154 /* Update the out_snd_device only before enabling the audio route */
1155 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301156 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301157 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301158 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301159 use_case_table[usecase->id],
1160 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001161 /* Update voc calibration before enabling VoIP route */
1162 if (usecase->type == VOIP_CALL)
1163 status = platform_switch_voice_call_device_post(adev->platform,
1164 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001165 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301166 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301167 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 }
1169 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 }
1171}
1172
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301173static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001174 struct audio_usecase *uc_info,
1175 snd_device_t snd_device)
1176{
1177 struct listnode *node;
1178 struct audio_usecase *usecase;
1179 bool switch_device[AUDIO_USECASE_MAX];
1180 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301181 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001182 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001183
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301184 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1185 snd_device);
1186 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301187
1188 /*
1189 * Make sure out devices is checked against out codec backend device and
1190 * also in devices against in codec backend. Checking out device against in
1191 * codec backend or vice versa causes issues.
1192 */
1193 if (uc_info->type == PCM_CAPTURE)
1194 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001195 /*
1196 * This function is to make sure that all the active capture usecases
1197 * are always routed to the same input sound device.
1198 * For example, if audio-record and voice-call usecases are currently
1199 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1200 * is received for voice call then we have to make sure that audio-record
1201 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1202 * because of the limitation that two devices cannot be enabled
1203 * at the same time if they share the same backend.
1204 */
1205 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1206 switch_device[i] = false;
1207
1208 list_for_each(node, &adev->usecase_list) {
1209 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301210 /*
1211 * TODO: Enhance below condition to handle BT sco/USB multi recording
1212 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001213 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301215 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301216 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301217 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301218 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001219 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001220 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1221 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001222 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001223 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001224 switch_device[usecase->id] = true;
1225 num_uc_to_switch++;
1226 }
1227 }
1228
1229 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001230 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001231
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301232 /* Make sure the previous devices to be disabled first and then enable the
1233 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001234 list_for_each(node, &adev->usecase_list) {
1235 usecase = node_to_item(node, struct audio_usecase, list);
1236 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001237 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001238 }
1239 }
1240
1241 list_for_each(node, &adev->usecase_list) {
1242 usecase = node_to_item(node, struct audio_usecase, list);
1243 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001244 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001245 }
1246 }
1247
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001248 /* Re-route all the usecases on the shared backend other than the
1249 specified usecase to new snd devices */
1250 list_for_each(node, &adev->usecase_list) {
1251 usecase = node_to_item(node, struct audio_usecase, list);
1252 /* Update the in_snd_device only before enabling the audio route */
1253 if (switch_device[usecase->id] ) {
1254 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001255 if (usecase->type != VOICE_CALL) {
1256 /* Update voc calibration before enabling VoIP route */
1257 if (usecase->type == VOIP_CALL)
1258 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001259 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001260 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301261 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001262 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001263 }
1264 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001265 }
1266}
1267
Mingming Yin3a941d42016-02-17 18:08:05 -08001268static void reset_hdmi_sink_caps(struct stream_out *out) {
1269 int i = 0;
1270
1271 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1272 out->supported_channel_masks[i] = 0;
1273 }
1274 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1275 out->supported_formats[i] = 0;
1276 }
1277 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1278 out->supported_sample_rates[i] = 0;
1279 }
1280}
1281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001283static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284{
Mingming Yin3a941d42016-02-17 18:08:05 -08001285 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001286 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287
Mingming Yin3a941d42016-02-17 18:08:05 -08001288 reset_hdmi_sink_caps(out);
1289
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001290 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001291 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001292 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001293 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001294 }
1295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001297 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001298 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001299 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001300 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1301 case 6:
1302 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1303 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1304 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1305 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1306 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1307 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308 break;
1309 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001310 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001311 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312 break;
1313 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001314
1315 // check channel format caps
1316 i = 0;
1317 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1318 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1319 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1320 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1321 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1322 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1323 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1324 }
1325
Ben Romberger1aaaf862017-04-06 17:49:46 -07001326 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1327 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1328 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1329 }
1330
Mingming Yin3a941d42016-02-17 18:08:05 -08001331 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1332 ALOGV(":%s HDMI supports DTS format", __func__);
1333 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1334 }
1335
1336 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1337 ALOGV(":%s HDMI supports DTS HD format", __func__);
1338 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1339 }
1340
Naresh Tanniru928f0862017-04-07 16:44:23 -07001341 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1342 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1343 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1344 }
1345
Mingming Yin3a941d42016-02-17 18:08:05 -08001346
1347 // check sample rate caps
1348 i = 0;
1349 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1350 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1351 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1352 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1353 }
1354 }
1355
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001356 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001357}
1358
Alexy Josephb1379942016-01-29 15:49:38 -08001359audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001360 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001361{
1362 struct audio_usecase *usecase;
1363 struct listnode *node;
1364
1365 list_for_each(node, &adev->usecase_list) {
1366 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001367 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001368 ALOGV("%s: usecase id %d", __func__, usecase->id);
1369 return usecase->id;
1370 }
1371 }
1372 return USECASE_INVALID;
1373}
1374
Alexy Josephb1379942016-01-29 15:49:38 -08001375struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001376 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377{
1378 struct audio_usecase *usecase;
1379 struct listnode *node;
1380
1381 list_for_each(node, &adev->usecase_list) {
1382 usecase = node_to_item(node, struct audio_usecase, list);
1383 if (usecase->id == uc_id)
1384 return usecase;
1385 }
1386 return NULL;
1387}
1388
Dhananjay Kumard4833242016-10-06 22:09:12 +05301389struct stream_in *get_next_active_input(const struct audio_device *adev)
1390{
1391 struct audio_usecase *usecase;
1392 struct listnode *node;
1393
1394 list_for_each_reverse(node, &adev->usecase_list) {
1395 usecase = node_to_item(node, struct audio_usecase, list);
1396 if (usecase->type == PCM_CAPTURE)
1397 return usecase->stream.in;
1398 }
1399 return NULL;
1400}
1401
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301402/*
1403 * is a true native playback active
1404 */
1405bool audio_is_true_native_stream_active(struct audio_device *adev)
1406{
1407 bool active = false;
1408 int i = 0;
1409 struct listnode *node;
1410
1411 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1412 ALOGV("%s:napb: not in true mode or non hdphones device",
1413 __func__);
1414 active = false;
1415 goto exit;
1416 }
1417
1418 list_for_each(node, &adev->usecase_list) {
1419 struct audio_usecase *uc;
1420 uc = node_to_item(node, struct audio_usecase, list);
1421 struct stream_out *curr_out =
1422 (struct stream_out*) uc->stream.out;
1423
1424 if (curr_out && PCM_PLAYBACK == uc->type) {
1425 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1426 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1427 uc->id, curr_out->sample_rate,
1428 curr_out->bit_width,
1429 platform_get_snd_device_name(uc->out_snd_device));
1430
1431 if (is_offload_usecase(uc->id) &&
1432 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1433 active = true;
1434 ALOGD("%s:napb:native stream detected", __func__);
1435 }
1436 }
1437 }
1438exit:
1439 return active;
1440}
1441
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301442/*
1443 * if native DSD playback active
1444 */
1445bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1446{
1447 bool active = false;
1448 struct listnode *node = NULL;
1449 struct audio_usecase *uc = NULL;
1450 struct stream_out *curr_out = NULL;
1451
1452 list_for_each(node, &adev->usecase_list) {
1453 uc = node_to_item(node, struct audio_usecase, list);
1454 curr_out = (struct stream_out*) uc->stream.out;
1455
1456 if (curr_out && PCM_PLAYBACK == uc->type &&
1457 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1458 active = true;
1459 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301460 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301461 }
1462 }
1463 return active;
1464}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301465
1466static bool force_device_switch(struct audio_usecase *usecase)
1467{
1468 bool ret = false;
1469 bool is_it_true_mode = false;
1470
1471 if (is_offload_usecase(usecase->id) &&
1472 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001473 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1474 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1475 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301476 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1477 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1478 (!is_it_true_mode && adev->native_playback_enabled)){
1479 ret = true;
1480 ALOGD("napb: time to toggle native mode");
1481 }
1482 }
1483
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301484 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301485 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1486 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301487 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001488 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301489 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301490 ALOGD("Force a2dp device switch to update new encoder config");
1491 ret = true;
1492 }
1493
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301494 return ret;
1495}
1496
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001497int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001499 snd_device_t out_snd_device = SND_DEVICE_NONE;
1500 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 struct audio_usecase *usecase = NULL;
1502 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001503 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001504 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001505 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301508 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1509
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001510 usecase = get_usecase_from_list(adev, uc_id);
1511 if (usecase == NULL) {
1512 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1513 return -EINVAL;
1514 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001516 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001517 (usecase->type == VOIP_CALL) ||
1518 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301519 if(usecase->stream.out == NULL) {
1520 ALOGE("%s: stream.out is NULL", __func__);
1521 return -EINVAL;
1522 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001523 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001524 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001525 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526 usecase->devices = usecase->stream.out->devices;
1527 } else {
1528 /*
1529 * If the voice call is active, use the sound devices of voice call usecase
1530 * so that it would not result any device switch. All the usecases will
1531 * be switched to new device when select_devices() is called for voice call
1532 * usecase. This is to avoid switching devices for voice call when
1533 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001534 * choose voice call device only if the use case device is
1535 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001537 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001538 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001539 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001540 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1541 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301542 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1543 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001544 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001545 in_snd_device = vc_usecase->in_snd_device;
1546 out_snd_device = vc_usecase->out_snd_device;
1547 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001548 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001549 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001550 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001551 if ((voip_usecase != NULL) &&
1552 (usecase->type == PCM_PLAYBACK) &&
1553 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001554 out_snd_device_backend_match = platform_check_backends_match(
1555 voip_usecase->out_snd_device,
1556 platform_get_output_snd_device(
1557 adev->platform,
1558 usecase->stream.out));
1559 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001560 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001561 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1562 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001563 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001564 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001565 in_snd_device = voip_usecase->in_snd_device;
1566 out_snd_device = voip_usecase->out_snd_device;
1567 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001568 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001569 hfp_ucid = audio_extn_hfp_get_usecase();
1570 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001571 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001572 in_snd_device = hfp_usecase->in_snd_device;
1573 out_snd_device = hfp_usecase->out_snd_device;
1574 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575 }
1576 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301577 if (usecase->stream.out == NULL) {
1578 ALOGE("%s: stream.out is NULL", __func__);
1579 return -EINVAL;
1580 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001581 usecase->devices = usecase->stream.out->devices;
1582 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001583 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001584 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001585 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001586 if (usecase->stream.out == adev->primary_output &&
1587 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001588 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001589 select_devices(adev, adev->active_input->usecase);
1590 }
1591 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001592 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301593 if (usecase->stream.in == NULL) {
1594 ALOGE("%s: stream.in is NULL", __func__);
1595 return -EINVAL;
1596 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001597 usecase->devices = usecase->stream.in->device;
1598 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001599 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001600 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001601 if (adev->active_input &&
1602 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301603 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1604 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1605 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001606 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001607 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001608 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1609 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001610 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001611 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001612 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001613 }
1614 }
1615
1616 if (out_snd_device == usecase->out_snd_device &&
1617 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301618
1619 if (!force_device_switch(usecase))
1620 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621 }
1622
sangwoobc677242013-08-08 16:53:43 +09001623 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001624 out_snd_device, platform_get_snd_device_name(out_snd_device),
1625 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 /*
1628 * Limitation: While in call, to do a device switch we need to disable
1629 * and enable both RX and TX devices though one of them is same as current
1630 * device.
1631 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001632 if ((usecase->type == VOICE_CALL) &&
1633 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1634 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001635 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001636 }
1637
1638 if (((usecase->type == VOICE_CALL) ||
1639 (usecase->type == VOIP_CALL)) &&
1640 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1641 /* Disable sidetone only if voice/voip call already exists */
1642 if (voice_is_call_state_active(adev) ||
1643 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001644 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001645
1646 /* Disable aanc only if voice call exists */
1647 if (voice_is_call_state_active(adev))
1648 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001649 }
1650
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001651 /* Disable current sound devices */
1652 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001653 disable_audio_route(adev, usecase);
1654 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 }
1656
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001657 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001658 disable_audio_route(adev, usecase);
1659 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 }
1661
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001662 /* Applicable only on the targets that has external modem.
1663 * New device information should be sent to modem before enabling
1664 * the devices to reduce in-call device switch time.
1665 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001666 if ((usecase->type == VOICE_CALL) &&
1667 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1668 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001669 status = platform_switch_voice_call_enable_device_config(adev->platform,
1670 out_snd_device,
1671 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001672 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001673
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001674 /* Enable new sound devices */
1675 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001676 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301677 if (platform_check_codec_asrc_support(adev->platform))
1678 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001679 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001680 }
1681
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001682 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301683 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001684 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001685 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001686
Avinash Vaish71a8b972014-07-24 15:36:33 +05301687 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001688 status = platform_switch_voice_call_device_post(adev->platform,
1689 out_snd_device,
1690 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301691 enable_audio_route_for_voice_usecases(adev, usecase);
1692 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001693
sangwoo170731f2013-06-08 15:36:36 +09001694 usecase->in_snd_device = in_snd_device;
1695 usecase->out_snd_device = out_snd_device;
1696
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301697 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1698 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301699 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001700 if ((24 == usecase->stream.out->bit_width) &&
1701 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1702 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1703 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1704 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1705 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1706 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1707 /*
1708 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1709 * configured device sample rate, if not update the COPP rate to be equal to the
1710 * device sample rate, else open COPP at stream sample rate
1711 */
1712 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1713 usecase->stream.out->sample_rate,
1714 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301715 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1716 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001717 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1718 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1719 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1720 }
1721
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001722 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001723 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001724 audio_extn_gef_notify_device_config(
1725 usecase->stream.out->devices,
1726 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001727 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001728 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001729 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301730 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001731 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001732
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001733 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001734 /* Enable aanc only if voice call exists */
1735 if (voice_is_call_state_active(adev))
1736 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1737
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001738 /* Enable sidetone only if other voice/voip call already exists */
1739 if (voice_is_call_state_active(adev) ||
1740 voice_extn_compress_voip_is_started(adev))
1741 voice_set_sidetone(adev, out_snd_device, true);
1742 }
1743
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001744 /* Applicable only on the targets that has external modem.
1745 * Enable device command should be sent to modem only after
1746 * enabling voice call mixer controls
1747 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001748 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001749 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1750 out_snd_device,
1751 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301752 ALOGD("%s: done",__func__);
1753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 return status;
1755}
1756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757static int stop_input_stream(struct stream_in *in)
1758{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301759 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 struct audio_usecase *uc_info;
1761 struct audio_device *adev = in->dev;
1762
Eric Laurent994a6932013-07-17 11:51:42 -07001763 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001764 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 uc_info = get_usecase_from_list(adev, in->usecase);
1766 if (uc_info == NULL) {
1767 ALOGE("%s: Could not find the usecase (%d) in the list",
1768 __func__, in->usecase);
1769 return -EINVAL;
1770 }
1771
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001772 /* Close in-call recording streams */
1773 voice_check_and_stop_incall_rec_usecase(adev, in);
1774
Eric Laurent150dbfe2013-02-27 14:31:02 -08001775 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001776 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001777
1778 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001779 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001781 list_remove(&uc_info->list);
1782 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001784 adev->active_input = get_next_active_input(adev);
1785
Eric Laurent994a6932013-07-17 11:51:42 -07001786 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 return ret;
1788}
1789
1790int start_input_stream(struct stream_in *in)
1791{
1792 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001793 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 struct audio_usecase *uc_info;
1795 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301796 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797
Mingming Yin2664a5b2015-09-03 10:53:11 -07001798 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1799 if (get_usecase_from_list(adev, usecase) == NULL)
1800 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301801 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1802 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001803
Naresh Tanniru80659832014-06-04 18:17:56 +05301804
1805 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301806 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301807 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301808 goto error_config;
1809 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301810
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001811 /* Check if source matches incall recording usecase criteria */
1812 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1813 if (ret)
1814 goto error_config;
1815 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001816 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1817
1818 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1819 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1820 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001821 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001822 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001823
Eric Laurentb23d5282013-05-14 15:27:20 -07001824 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825 if (in->pcm_device_id < 0) {
1826 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1827 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001828 ret = -EINVAL;
1829 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831
1832 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001834
1835 if (!uc_info) {
1836 ret = -ENOMEM;
1837 goto error_config;
1838 }
1839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 uc_info->id = in->usecase;
1841 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001842 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001843 uc_info->devices = in->device;
1844 uc_info->in_snd_device = SND_DEVICE_NONE;
1845 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001847 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301848 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1849 adev->perf_lock_opts,
1850 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301853 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1854 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001855
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301856 if (audio_extn_cin_attached_usecase(in->usecase)) {
1857 ret = audio_extn_cin_start_input_stream(in);
1858 if (ret)
1859 goto error_open;
1860 else
1861 goto done_open;
1862 }
1863
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001864 unsigned int flags = PCM_IN;
1865 unsigned int pcm_open_retry_count = 0;
1866
1867 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1868 flags |= PCM_MMAP | PCM_NOIRQ;
1869 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001870 } else if (in->realtime) {
1871 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001872 }
1873
1874 while (1) {
1875 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1876 flags, &in->config);
1877 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1878 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1879 if (in->pcm != NULL) {
1880 pcm_close(in->pcm);
1881 in->pcm = NULL;
1882 }
1883 if (pcm_open_retry_count-- == 0) {
1884 ret = -EIO;
1885 goto error_open;
1886 }
1887 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1888 continue;
1889 }
1890 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001892
1893 ALOGV("%s: pcm_prepare", __func__);
1894 ret = pcm_prepare(in->pcm);
1895 if (ret < 0) {
1896 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1897 pcm_close(in->pcm);
1898 in->pcm = NULL;
1899 goto error_open;
1900 }
1901
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001902 register_in_stream(in);
1903 if (in->realtime) {
1904 ret = pcm_start(in->pcm);
1905 if (ret < 0)
1906 goto error_open;
1907 }
1908
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301909done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301910 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001911 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001912
Eric Laurentc8400632013-02-14 19:04:54 -08001913 return ret;
1914
1915error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301916 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001918error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301919 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301920 /*
1921 * sleep 50ms to allow sufficient time for kernel
1922 * drivers to recover incases like SSR.
1923 */
1924 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001925 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001926
1927 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928}
1929
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001930void lock_input_stream(struct stream_in *in)
1931{
1932 pthread_mutex_lock(&in->pre_lock);
1933 pthread_mutex_lock(&in->lock);
1934 pthread_mutex_unlock(&in->pre_lock);
1935}
1936
1937void lock_output_stream(struct stream_out *out)
1938{
1939 pthread_mutex_lock(&out->pre_lock);
1940 pthread_mutex_lock(&out->lock);
1941 pthread_mutex_unlock(&out->pre_lock);
1942}
1943
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001944/* must be called with out->lock locked */
1945static int send_offload_cmd_l(struct stream_out* out, int command)
1946{
1947 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1948
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001949 if (!cmd) {
1950 ALOGE("failed to allocate mem for command 0x%x", command);
1951 return -ENOMEM;
1952 }
1953
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001954 ALOGVV("%s %d", __func__, command);
1955
1956 cmd->cmd = command;
1957 list_add_tail(&out->offload_cmd_list, &cmd->node);
1958 pthread_cond_signal(&out->offload_cond);
1959 return 0;
1960}
1961
1962/* must be called iwth out->lock locked */
1963static void stop_compressed_output_l(struct stream_out *out)
1964{
1965 out->offload_state = OFFLOAD_STATE_IDLE;
1966 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001967 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001968 if (out->compr != NULL) {
1969 compress_stop(out->compr);
1970 while (out->offload_thread_blocked) {
1971 pthread_cond_wait(&out->cond, &out->lock);
1972 }
1973 }
1974}
1975
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001976bool is_offload_usecase(audio_usecase_t uc_id)
1977{
1978 unsigned int i;
1979 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1980 if (uc_id == offload_usecases[i])
1981 return true;
1982 }
1983 return false;
1984}
1985
Dhananjay Kumarac341582017-02-23 23:42:25 +05301986static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001987{
vivek mehta446c3962015-09-14 10:57:35 -07001988 audio_usecase_t ret_uc = USECASE_INVALID;
1989 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001990 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001991 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05301992 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07001993 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1994 else
1995 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001996
vivek mehta446c3962015-09-14 10:57:35 -07001997 pthread_mutex_lock(&adev->lock);
1998 if (get_usecase_from_list(adev, ret_uc) != NULL)
1999 ret_uc = USECASE_INVALID;
2000 pthread_mutex_unlock(&adev->lock);
2001
2002 return ret_uc;
2003 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002004
2005 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002006 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2007 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2008 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2009 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002010 break;
2011 }
2012 }
vivek mehta446c3962015-09-14 10:57:35 -07002013
2014 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2015 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002016}
2017
2018static void free_offload_usecase(struct audio_device *adev,
2019 audio_usecase_t uc_id)
2020{
vivek mehta446c3962015-09-14 10:57:35 -07002021 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002022 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002023
2024 if (!adev->multi_offload_enable)
2025 return;
2026
2027 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2028 if (offload_usecases[offload_uc_index] == uc_id) {
2029 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002030 break;
2031 }
2032 }
2033 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2034}
2035
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002036static void *offload_thread_loop(void *context)
2037{
2038 struct stream_out *out = (struct stream_out *) context;
2039 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002040 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002041
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2043 set_sched_policy(0, SP_FOREGROUND);
2044 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2045
2046 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002047 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002048 for (;;) {
2049 struct offload_cmd *cmd = NULL;
2050 stream_callback_event_t event;
2051 bool send_callback = false;
2052
2053 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2054 __func__, list_empty(&out->offload_cmd_list),
2055 out->offload_state);
2056 if (list_empty(&out->offload_cmd_list)) {
2057 ALOGV("%s SLEEPING", __func__);
2058 pthread_cond_wait(&out->offload_cond, &out->lock);
2059 ALOGV("%s RUNNING", __func__);
2060 continue;
2061 }
2062
2063 item = list_head(&out->offload_cmd_list);
2064 cmd = node_to_item(item, struct offload_cmd, node);
2065 list_remove(item);
2066
2067 ALOGVV("%s STATE %d CMD %d out->compr %p",
2068 __func__, out->offload_state, cmd->cmd, out->compr);
2069
2070 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2071 free(cmd);
2072 break;
2073 }
2074
2075 if (out->compr == NULL) {
2076 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002077 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 pthread_cond_signal(&out->cond);
2079 continue;
2080 }
2081 out->offload_thread_blocked = true;
2082 pthread_mutex_unlock(&out->lock);
2083 send_callback = false;
2084 switch(cmd->cmd) {
2085 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002086 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002088 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 send_callback = true;
2090 event = STREAM_CBK_EVENT_WRITE_READY;
2091 break;
2092 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002093 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302094 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002095 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302096 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002097 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302098 if (ret < 0)
2099 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302100 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302101 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002102 compress_drain(out->compr);
2103 else
2104 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302105 if (ret != -ENETRESET) {
2106 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302107 pthread_mutex_lock(&out->lock);
2108 out->send_new_metadata = 1;
2109 out->send_next_track_params = true;
2110 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302111 event = STREAM_CBK_EVENT_DRAIN_READY;
2112 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2113 } else
2114 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115 break;
2116 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002117 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002118 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002119 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120 send_callback = true;
2121 event = STREAM_CBK_EVENT_DRAIN_READY;
2122 break;
2123 default:
2124 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2125 break;
2126 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002127 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002128 out->offload_thread_blocked = false;
2129 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002130 if (send_callback && out->client_callback) {
2131 ALOGVV("%s: sending client_callback event %d", __func__, event);
2132 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002133 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 free(cmd);
2135 }
2136
2137 pthread_cond_signal(&out->cond);
2138 while (!list_empty(&out->offload_cmd_list)) {
2139 item = list_head(&out->offload_cmd_list);
2140 list_remove(item);
2141 free(node_to_item(item, struct offload_cmd, node));
2142 }
2143 pthread_mutex_unlock(&out->lock);
2144
2145 return NULL;
2146}
2147
2148static int create_offload_callback_thread(struct stream_out *out)
2149{
2150 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2151 list_init(&out->offload_cmd_list);
2152 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2153 offload_thread_loop, out);
2154 return 0;
2155}
2156
2157static int destroy_offload_callback_thread(struct stream_out *out)
2158{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002159 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002160 stop_compressed_output_l(out);
2161 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2162
2163 pthread_mutex_unlock(&out->lock);
2164 pthread_join(out->offload_thread, (void **) NULL);
2165 pthread_cond_destroy(&out->offload_cond);
2166
2167 return 0;
2168}
2169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170static int stop_output_stream(struct stream_out *out)
2171{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302172 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 struct audio_usecase *uc_info;
2174 struct audio_device *adev = out->dev;
2175
Eric Laurent994a6932013-07-17 11:51:42 -07002176 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002177 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002178 uc_info = get_usecase_from_list(adev, out->usecase);
2179 if (uc_info == NULL) {
2180 ALOGE("%s: Could not find the usecase (%d) in the list",
2181 __func__, out->usecase);
2182 return -EINVAL;
2183 }
2184
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002185 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302186 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002187 if (adev->visualizer_stop_output != NULL)
2188 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002189
2190 audio_extn_dts_remove_state_notifier_node(out->usecase);
2191
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002192 if (adev->offload_effects_stop_output != NULL)
2193 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2194 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002195
Eric Laurent150dbfe2013-02-27 14:31:02 -08002196 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002197 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002198
2199 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002200 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002201
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002202 list_remove(&uc_info->list);
2203 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002205 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302206 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002207 ALOGV("Disable passthrough , reset mixer to pcm");
2208 /* NO_PASSTHROUGH */
2209 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002210 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002211 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2212 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002213
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302214 /* Must be called after removing the usecase from list */
2215 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302216 audio_extn_keep_alive_start();
2217
Naresh Tanniru85819452017-05-04 18:55:45 -07002218 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2219 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2220 if (ret < 0)
2221 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2222 }
2223
Eric Laurent994a6932013-07-17 11:51:42 -07002224 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 return ret;
2226}
2227
2228int start_output_stream(struct stream_out *out)
2229{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 struct audio_usecase *uc_info;
2232 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302233 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002234 char mixer_ctl_name[128];
2235 struct mixer_ctl *ctl = NULL;
2236 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002238 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2239 ret = -EINVAL;
2240 goto error_config;
2241 }
2242
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302243 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2244 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2245 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302246
Naresh Tanniru80659832014-06-04 18:17:56 +05302247 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302248 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302249 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302250 goto error_config;
2251 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302252
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302253 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2254 if (!audio_extn_a2dp_is_ready()) {
2255 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2256 //combo usecase just by pass a2dp
2257 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2258 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2259 } else {
2260 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2261 ret = -EAGAIN;
2262 goto error_config;
2263 }
2264 }
2265 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002266 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 if (out->pcm_device_id < 0) {
2268 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2269 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002270 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002271 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272 }
2273
2274 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002275
2276 if (!uc_info) {
2277 ret = -ENOMEM;
2278 goto error_config;
2279 }
2280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 uc_info->id = out->usecase;
2282 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002283 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002284 uc_info->devices = out->devices;
2285 uc_info->in_snd_device = SND_DEVICE_NONE;
2286 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002287 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002288
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302289 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2290 adev->perf_lock_opts,
2291 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302292
2293 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2294 audio_extn_keep_alive_stop();
2295 if (audio_extn_passthru_is_enabled() &&
2296 audio_extn_passthru_is_passthrough_stream(out)) {
2297 audio_extn_passthru_on_start(out);
2298 audio_extn_passthru_update_stream_configuration(adev, out);
2299 }
2300 }
2301
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002302 select_devices(adev, out->usecase);
2303
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002304 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2305 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002306 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002307 unsigned int flags = PCM_OUT;
2308 unsigned int pcm_open_retry_count = 0;
2309 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2310 flags |= PCM_MMAP | PCM_NOIRQ;
2311 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002312 } else if (out->realtime) {
2313 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002314 } else
2315 flags |= PCM_MONOTONIC;
2316
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002317 if ((adev->vr_audio_mode_enabled) &&
2318 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2319 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2320 "PCM_Dev %d Topology", out->pcm_device_id);
2321 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2322 if (!ctl) {
2323 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2324 __func__, mixer_ctl_name);
2325 } else {
2326 //if success use ULLPP
2327 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2328 __func__, mixer_ctl_name, out->pcm_device_id);
2329 //There is a still a possibility that some sessions
2330 // that request for FAST|RAW when 3D audio is active
2331 //can go through ULLPP. Ideally we expects apps to
2332 //listen to audio focus and stop concurrent playback
2333 //Also, we will look for mode flag (voice_in_communication)
2334 //before enabling the realtime flag.
2335 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2336 }
2337 }
2338
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002339 while (1) {
2340 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2341 flags, &out->config);
2342 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2343 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2344 if (out->pcm != NULL) {
2345 pcm_close(out->pcm);
2346 out->pcm = NULL;
2347 }
2348 if (pcm_open_retry_count-- == 0) {
2349 ret = -EIO;
2350 goto error_open;
2351 }
2352 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2353 continue;
2354 }
2355 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002356 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002357
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002358 ALOGV("%s: pcm_prepare", __func__);
2359 if (pcm_is_ready(out->pcm)) {
2360 ret = pcm_prepare(out->pcm);
2361 if (ret < 0) {
2362 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2363 pcm_close(out->pcm);
2364 out->pcm = NULL;
2365 goto error_open;
2366 }
2367 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302368 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302369 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2370
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002372 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302373 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002375 out->compr = compress_open(adev->snd_card,
2376 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 COMPRESS_IN, &out->compr_config);
2378 if (out->compr && !is_compress_ready(out->compr)) {
2379 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2380 compress_close(out->compr);
2381 out->compr = NULL;
2382 ret = -EIO;
2383 goto error_open;
2384 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302385 /* compress_open sends params of the track, so reset the flag here */
2386 out->is_compr_metadata_avail = false;
2387
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002388 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002390
Fred Oh3f43e742015-03-04 18:42:34 -08002391 /* Since small bufs uses blocking writes, a write will be blocked
2392 for the default max poll time (20s) in the event of an SSR.
2393 Reduce the poll time to observe and deal with SSR faster.
2394 */
Ashish Jain5106d362016-05-11 19:23:33 +05302395 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002396 compress_set_max_poll_wait(out->compr, 1000);
2397 }
2398
Manish Dewangan69426c82017-01-30 17:35:36 +05302399 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302400 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302401
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002402 audio_extn_dts_create_state_notifier_node(out->usecase);
2403 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2404 popcount(out->channel_mask),
2405 out->playback_started);
2406
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002407#ifdef DS1_DOLBY_DDP_ENABLED
2408 if (audio_extn_is_dolby_format(out->format))
2409 audio_extn_dolby_send_ddp_endp_params(adev);
2410#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302411 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2412 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002413 if (adev->visualizer_start_output != NULL)
2414 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2415 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302416 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002417 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002418 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002420
2421 if (ret == 0) {
2422 register_out_stream(out);
2423 if (out->realtime) {
2424 ret = pcm_start(out->pcm);
2425 if (ret < 0)
2426 goto error_open;
2427 }
2428 }
2429
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302430 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002431 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002432
Naresh Tanniru85819452017-05-04 18:55:45 -07002433 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2434 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out);
2435 if (ret < 0)
2436 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2437 }
2438
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002439 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302441 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002443error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302444 /*
2445 * sleep 50ms to allow sufficient time for kernel
2446 * drivers to recover incases like SSR.
2447 */
2448 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002449 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450}
2451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452static int check_input_parameters(uint32_t sample_rate,
2453 audio_format_t format,
2454 int channel_count)
2455{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002456 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302458 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2459 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2460 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002461 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302462 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002463
2464 switch (channel_count) {
2465 case 1:
2466 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302467 case 3:
2468 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002469 case 6:
2470 break;
2471 default:
2472 ret = -EINVAL;
2473 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474
2475 switch (sample_rate) {
2476 case 8000:
2477 case 11025:
2478 case 12000:
2479 case 16000:
2480 case 22050:
2481 case 24000:
2482 case 32000:
2483 case 44100:
2484 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302485 case 96000:
2486 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 break;
2488 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002489 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 }
2491
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002492 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493}
2494
2495static size_t get_input_buffer_size(uint32_t sample_rate,
2496 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002497 int channel_count,
2498 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499{
2500 size_t size = 0;
2501
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002502 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2503 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002505 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002506 if (is_low_latency)
2507 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302508
2509 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002511 /* make sure the size is multiple of 32 bytes
2512 * At 48 kHz mono 16-bit PCM:
2513 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2514 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2515 */
2516 size += 0x1f;
2517 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002518
2519 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520}
2521
Ashish Jain058165c2016-09-28 23:18:48 +05302522static size_t get_output_period_size(uint32_t sample_rate,
2523 audio_format_t format,
2524 int channel_count,
2525 int duration /*in millisecs*/)
2526{
2527 size_t size = 0;
2528 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2529
2530 if ((duration == 0) || (sample_rate == 0) ||
2531 (bytes_per_sample == 0) || (channel_count == 0)) {
2532 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2533 bytes_per_sample, channel_count);
2534 return -EINVAL;
2535 }
2536
2537 size = (sample_rate *
2538 duration *
2539 bytes_per_sample *
2540 channel_count) / 1000;
2541 /*
2542 * To have same PCM samples for all channels, the buffer size requires to
2543 * be multiple of (number of channels * bytes per sample)
2544 * For writes to succeed, the buffer must be written at address which is multiple of 32
2545 */
2546 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2547
2548 return (size/(channel_count * bytes_per_sample));
2549}
2550
Ashish Jain5106d362016-05-11 19:23:33 +05302551static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2552{
2553 uint64_t actual_frames_rendered = 0;
2554 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2555
2556 /* This adjustment accounts for buffering after app processor.
2557 * It is based on estimated DSP latency per use case, rather than exact.
2558 */
2559 int64_t platform_latency = platform_render_latency(out->usecase) *
2560 out->sample_rate / 1000000LL;
2561
2562 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2563 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2564 * hence only estimate.
2565 */
2566 int64_t signed_frames = out->written - kernel_buffer_size;
2567
2568 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2569
2570 if (signed_frames > 0)
2571 actual_frames_rendered = signed_frames;
2572
2573 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2574 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2575 (long long int)out->written, (int)kernel_buffer_size,
2576 audio_bytes_per_sample(out->compr_config.codec->format),
2577 popcount(out->channel_mask));
2578
2579 return actual_frames_rendered;
2580}
2581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2583{
2584 struct stream_out *out = (struct stream_out *)stream;
2585
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002586 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587}
2588
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002589static int out_set_sample_rate(struct audio_stream *stream __unused,
2590 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591{
2592 return -ENOSYS;
2593}
2594
2595static size_t out_get_buffer_size(const struct audio_stream *stream)
2596{
2597 struct stream_out *out = (struct stream_out *)stream;
2598
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302599 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2600 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2601 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2602 else
2603 return out->compr_config.fragment_size;
2604 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002605 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302606 else if (is_offload_usecase(out->usecase) &&
2607 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302608 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002609
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002610 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002611 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612}
2613
2614static uint32_t out_get_channels(const struct audio_stream *stream)
2615{
2616 struct stream_out *out = (struct stream_out *)stream;
2617
2618 return out->channel_mask;
2619}
2620
2621static audio_format_t out_get_format(const struct audio_stream *stream)
2622{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 struct stream_out *out = (struct stream_out *)stream;
2624
2625 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626}
2627
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002628static int out_set_format(struct audio_stream *stream __unused,
2629 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630{
2631 return -ENOSYS;
2632}
2633
2634static int out_standby(struct audio_stream *stream)
2635{
2636 struct stream_out *out = (struct stream_out *)stream;
2637 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002638
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302639 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2640 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002642 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002644 if (adev->adm_deregister_stream)
2645 adev->adm_deregister_stream(adev->adm_data, out->handle);
2646
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002647 if (is_offload_usecase(out->usecase))
2648 stop_compressed_output_l(out);
2649
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002650 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002652 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2653 voice_extn_compress_voip_close_output_stream(stream);
2654 pthread_mutex_unlock(&adev->lock);
2655 pthread_mutex_unlock(&out->lock);
2656 ALOGD("VOIP output entered standby");
2657 return 0;
2658 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002659 if (out->pcm) {
2660 pcm_close(out->pcm);
2661 out->pcm = NULL;
2662 }
2663 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002664 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302665 out->send_next_track_params = false;
2666 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002667 out->gapless_mdata.encoder_delay = 0;
2668 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002669 if (out->compr != NULL) {
2670 compress_close(out->compr);
2671 out->compr = NULL;
2672 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002673 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002675 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 }
2677 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302678 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 return 0;
2680}
2681
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002682static int out_dump(const struct audio_stream *stream __unused,
2683 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684{
2685 return 0;
2686}
2687
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002688static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2689{
2690 int ret = 0;
2691 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002692
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002693 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002694 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002695 return -EINVAL;
2696 }
2697
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302698 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002699
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002700 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2701 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302702 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002703 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002704 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2705 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302706 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002707 }
2708
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002709 ALOGV("%s new encoder delay %u and padding %u", __func__,
2710 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2711
2712 return 0;
2713}
2714
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002715static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2716{
2717 return out == adev->primary_output || out == adev->voice_tx_output;
2718}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2721{
2722 struct stream_out *out = (struct stream_out *)stream;
2723 struct audio_device *adev = out->dev;
2724 struct str_parms *parms;
2725 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002726 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727
sangwoobc677242013-08-08 16:53:43 +09002728 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002729 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302731 if (!parms)
2732 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002733 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2734 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002736 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002737 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002739 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002740 * When HDMI cable is unplugged the music playback is paused and
2741 * the policy manager sends routing=0. But the audioflinger continues
2742 * to write data until standby time (3sec). As the HDMI core is
2743 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002744 * Avoid this by routing audio to speaker until standby.
2745 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002746 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2747 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302748 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002749 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2750 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002751 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302752 /*
2753 * When A2DP is disconnected the
2754 * music playback is paused and the policy manager sends routing=0
2755 * But the audioflingercontinues to write data until standby time
2756 * (3sec). As BT is turned off, the write gets blocked.
2757 * Avoid this by routing audio to speaker until standby.
2758 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002759 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302760 (val == AUDIO_DEVICE_NONE)) {
2761 val = AUDIO_DEVICE_OUT_SPEAKER;
2762 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302763 /* To avoid a2dp to sco overlapping / BT device improper state
2764 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302765 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302766 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2767 if (!audio_extn_a2dp_is_ready()) {
2768 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2769 //combo usecase just by pass a2dp
2770 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2771 val = AUDIO_DEVICE_OUT_SPEAKER;
2772 } else {
2773 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2774 /* update device to a2dp and don't route as BT returned error
2775 * However it is still possible a2dp routing called because
2776 * of current active device disconnection (like wired headset)
2777 */
2778 out->devices = val;
2779 pthread_mutex_unlock(&out->lock);
2780 pthread_mutex_unlock(&adev->lock);
2781 goto error;
2782 }
2783 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302784 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002785 /*
2786 * select_devices() call below switches all the usecases on the same
2787 * backend to the new device. Refer to check_usecases_codec_backend() in
2788 * the select_devices(). But how do we undo this?
2789 *
2790 * For example, music playback is active on headset (deep-buffer usecase)
2791 * and if we go to ringtones and select a ringtone, low-latency usecase
2792 * will be started on headset+speaker. As we can't enable headset+speaker
2793 * and headset devices at the same time, select_devices() switches the music
2794 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2795 * So when the ringtone playback is completed, how do we undo the same?
2796 *
2797 * We are relying on the out_set_parameters() call on deep-buffer output,
2798 * once the ringtone playback is ended.
2799 * NOTE: We should not check if the current devices are same as new devices.
2800 * Because select_devices() must be called to switch back the music
2801 * playback to headset.
2802 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002803 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002804 audio_devices_t new_dev = val;
2805 bool same_dev = out->devices == new_dev;
2806 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002807
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002808 if (output_drives_call(adev, out)) {
2809 if(!voice_is_in_call(adev)) {
2810 if (adev->mode == AUDIO_MODE_IN_CALL) {
2811 adev->current_call_output = out;
2812 ret = voice_start_call(adev);
2813 }
2814 } else {
2815 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002816 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002817 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002818 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002819
2820 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002821 if (!same_dev) {
2822 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302823 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2824 adev->perf_lock_opts,
2825 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002826 if (adev->adm_on_routing_change)
2827 adev->adm_on_routing_change(adev->adm_data,
2828 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002829 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002830 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302831 if (!same_dev)
2832 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002833 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002834 }
2835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002837 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002839
2840 if (out == adev->primary_output) {
2841 pthread_mutex_lock(&adev->lock);
2842 audio_extn_set_parameters(adev, parms);
2843 pthread_mutex_unlock(&adev->lock);
2844 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002845 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002846 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002847 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002848
2849 audio_extn_dts_create_state_notifier_node(out->usecase);
2850 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2851 popcount(out->channel_mask),
2852 out->playback_started);
2853
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002854 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002855 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002856
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302857 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2858 if (err >= 0) {
2859 strlcpy(out->profile, value, sizeof(out->profile));
2860 ALOGV("updating stream profile with value '%s'", out->profile);
2861 lock_output_stream(out);
2862 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2863 &adev->streams_output_cfg_list,
2864 out->devices, out->flags, out->format,
2865 out->sample_rate, out->bit_width,
2866 out->channel_mask, out->profile,
2867 &out->app_type_cfg);
2868 pthread_mutex_unlock(&out->lock);
2869 }
2870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302872error:
Eric Laurent994a6932013-07-17 11:51:42 -07002873 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 return ret;
2875}
2876
2877static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2878{
2879 struct stream_out *out = (struct stream_out *)stream;
2880 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002881 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 char value[256];
2883 struct str_parms *reply = str_parms_create();
2884 size_t i, j;
2885 int ret;
2886 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002887
2888 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002889 if (reply) {
2890 str_parms_destroy(reply);
2891 }
2892 if (query) {
2893 str_parms_destroy(query);
2894 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002895 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2896 return NULL;
2897 }
2898
Eric Laurent994a6932013-07-17 11:51:42 -07002899 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2901 if (ret >= 0) {
2902 value[0] = '\0';
2903 i = 0;
2904 while (out->supported_channel_masks[i] != 0) {
2905 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2906 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2907 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002908 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002910 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002911 first = false;
2912 break;
2913 }
2914 }
2915 i++;
2916 }
2917 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2918 str = str_parms_to_str(reply);
2919 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002920 voice_extn_out_get_parameters(out, query, reply);
2921 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002922 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002923 free(str);
2924 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002925 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002926 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002927
Alexy Joseph62142aa2015-11-16 15:10:34 -08002928
2929 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2930 if (ret >= 0) {
2931 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05302932 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
2933 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08002934 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302935 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002936 } else {
2937 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302938 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002939 }
2940 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002941 if (str)
2942 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002943 str = str_parms_to_str(reply);
2944 }
2945
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002946 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2947 if (ret >= 0) {
2948 value[0] = '\0';
2949 i = 0;
2950 first = true;
2951 while (out->supported_formats[i] != 0) {
2952 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2953 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2954 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002955 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002956 }
2957 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2958 first = false;
2959 break;
2960 }
2961 }
2962 i++;
2963 }
2964 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002965 if (str)
2966 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002967 str = str_parms_to_str(reply);
2968 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002969
2970 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2971 if (ret >= 0) {
2972 value[0] = '\0';
2973 i = 0;
2974 first = true;
2975 while (out->supported_sample_rates[i] != 0) {
2976 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2977 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2978 if (!first) {
2979 strlcat(value, "|", sizeof(value));
2980 }
2981 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2982 first = false;
2983 break;
2984 }
2985 }
2986 i++;
2987 }
2988 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2989 if (str)
2990 free(str);
2991 str = str_parms_to_str(reply);
2992 }
2993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 str_parms_destroy(query);
2995 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002996 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997 return str;
2998}
2999
3000static uint32_t out_get_latency(const struct audio_stream_out *stream)
3001{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003002 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003004 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005
Alexy Josephaa54c872014-12-03 02:46:47 -08003006 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303007 lock_output_stream(out);
3008 latency = audio_extn_utils_compress_get_dsp_latency(out);
3009 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003010 } else if (out->realtime) {
3011 // since the buffer won't be filled up faster than realtime,
3012 // return a smaller number
3013 if (out->config.rate)
3014 period_ms = (out->af_period_multiplier * out->config.period_size *
3015 1000) / (out->config.rate);
3016 else
3017 period_ms = 0;
3018 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003019 } else {
3020 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003021 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003022 }
3023
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003024 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3025 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3026 latency += audio_extn_a2dp_get_encoder_latency();
3027
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303028 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003029 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030}
3031
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303032static float AmpToDb(float amplification)
3033{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303034 float db = DSD_VOLUME_MIN_DB;
3035 if (amplification > 0) {
3036 db = 20 * log10(amplification);
3037 if(db < DSD_VOLUME_MIN_DB)
3038 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303039 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303040 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303041}
3042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043static int out_set_volume(struct audio_stream_out *stream, float left,
3044 float right)
3045{
Eric Laurenta9024de2013-04-04 09:19:12 -07003046 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 int volume[2];
3048
Eric Laurenta9024de2013-04-04 09:19:12 -07003049 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3050 /* only take left channel into account: the API is for stereo anyway */
3051 out->muted = (left == 0.0f);
3052 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003053 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303054 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003055 /*
3056 * Set mute or umute on HDMI passthrough stream.
3057 * Only take left channel into account.
3058 * Mute is 0 and unmute 1
3059 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303060 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303061 } else if (out->format == AUDIO_FORMAT_DSD){
3062 char mixer_ctl_name[128] = "DSD Volume";
3063 struct audio_device *adev = out->dev;
3064 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3065
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)(AmpToDb(left));
3072 volume[1] = (int)(AmpToDb(right));
3073 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3074 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003075 } else {
3076 char mixer_ctl_name[128];
3077 struct audio_device *adev = out->dev;
3078 struct mixer_ctl *ctl;
3079 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003080 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003082 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3083 "Compress Playback %d Volume", pcm_device_id);
3084 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3085 if (!ctl) {
3086 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3087 __func__, mixer_ctl_name);
3088 return -EINVAL;
3089 }
3090 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3091 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3092 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3093 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003094 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003095 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 return -ENOSYS;
3098}
3099
3100static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3101 size_t bytes)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
3104 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303105 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003106 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003108 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303109
Naresh Tanniru80659832014-06-04 18:17:56 +05303110 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003111
Dhananjay Kumarac341582017-02-23 23:42:25 +05303112 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303113 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303114 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3115 pthread_mutex_unlock(&out->lock);
3116 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303117 } else {
3118 /* increase written size during SSR to avoid mismatch
3119 * with the written frames count in AF
3120 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003121 // bytes per frame
3122 size_t bpf = audio_bytes_per_sample(out->format) *
3123 audio_channel_count_from_out_mask(out->channel_mask);
3124 if (bpf != 0)
3125 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303126 ALOGD(" %s: sound card is not active/SSR state", __func__);
3127 ret= -EIO;
3128 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303129 }
3130 }
3131
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303132 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303133 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3134 if (audio_bytes_per_sample(out->format) != 0)
3135 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3136 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303137 goto exit;
3138 }
3139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003141 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003142 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003143 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3144 ret = voice_extn_compress_voip_start_output_stream(out);
3145 else
3146 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003147 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003148 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003150 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151 goto exit;
3152 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003153
3154 if (last_known_cal_step != -1) {
3155 ALOGD("%s: retry previous failed cal level set", __func__);
3156 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159
Ashish Jain81eb2a82015-05-13 10:52:34 +05303160 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003161 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303162 adev->is_channel_status_set = true;
3163 }
3164
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003165 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003166 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003167 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003168 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003169 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3170 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303171 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3172 ALOGD("copl(%p):send next track params in gapless", out);
3173 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3174 out->send_next_track_params = false;
3175 out->is_compr_metadata_avail = false;
3176 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003177 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303178 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303179 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003180
Ashish Jain83a6cc22016-06-28 14:34:17 +05303181 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303182 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303183 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303184 pthread_mutex_unlock(&out->lock);
3185 return -EINVAL;
3186 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303187 audio_format_t dst_format = out->hal_op_format;
3188 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303189
3190 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3191 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3192
Ashish Jain83a6cc22016-06-28 14:34:17 +05303193 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303194 dst_format,
3195 buffer,
3196 src_format,
3197 frames);
3198
Ashish Jain83a6cc22016-06-28 14:34:17 +05303199 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303200 bytes_to_write);
3201
3202 /*Convert written bytes in audio flinger format*/
3203 if (ret > 0)
3204 ret = ((ret * format_to_bitwidth_table[out->format]) /
3205 format_to_bitwidth_table[dst_format]);
3206 }
3207 } else
3208 ret = compress_write(out->compr, buffer, bytes);
3209
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303210 if (ret < 0)
3211 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303212 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303213 /*msg to cb thread only if non blocking write is enabled*/
3214 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303215 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003216 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303217 } else if (-ENETRESET == ret) {
3218 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3219 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3220 pthread_mutex_unlock(&out->lock);
3221 out_standby(&out->stream.common);
3222 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003223 }
Ashish Jain5106d362016-05-11 19:23:33 +05303224 if ( ret == (ssize_t)bytes && !out->non_blocking)
3225 out->written += bytes;
3226
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303227 /* Call compr start only when non-zero bytes of data is there to be rendered */
3228 if (!out->playback_started && ret > 0) {
3229 int status = compress_start(out->compr);
3230 if (status < 0) {
3231 ret = status;
3232 ALOGE("%s: compr start failed with err %d", __func__, errno);
3233 goto exit;
3234 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003235 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236 out->playback_started = 1;
3237 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003238
3239 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3240 popcount(out->channel_mask),
3241 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003242 }
3243 pthread_mutex_unlock(&out->lock);
3244 return ret;
3245 } else {
3246 if (out->pcm) {
3247 if (out->muted)
3248 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003249
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303250 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003251
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003252 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003253
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003254 if (out->config.rate)
3255 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3256 out->config.rate;
3257
3258 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3259
3260 request_out_focus(out, ns);
3261
3262 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003263 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003264 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303265 out->convert_buffer != NULL) {
3266
3267 memcpy_by_audio_format(out->convert_buffer,
3268 out->hal_op_format,
3269 buffer,
3270 out->hal_ip_format,
3271 out->config.period_size * out->config.channels);
3272
3273 ret = pcm_write(out->pcm, out->convert_buffer,
3274 (out->config.period_size *
3275 out->config.channels *
3276 format_to_bitwidth_table[out->hal_op_format]));
3277 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303278 /*
3279 * To avoid underrun in DSP when the application is not pumping
3280 * data at required rate, check for the no. of bytes and ignore
3281 * pcm_write if it is less than actual buffer size.
3282 * It is a work around to a change in compress VOIP driver.
3283 */
3284 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3285 bytes < (out->config.period_size * out->config.channels *
3286 audio_bytes_per_sample(out->format))) {
3287 size_t voip_buf_size =
3288 out->config.period_size * out->config.channels *
3289 audio_bytes_per_sample(out->format);
3290 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3291 __func__, bytes, voip_buf_size);
3292 usleep(((uint64_t)voip_buf_size - bytes) *
3293 1000000 / audio_stream_out_frame_size(stream) /
3294 out_get_sample_rate(&out->stream.common));
3295 ret = 0;
3296 } else
3297 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303298 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003299
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003300 release_out_focus(out);
3301
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303302 if (ret < 0)
3303 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303304 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3305 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3306 else
3307 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003308 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 }
3310
3311exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303312 /* ToDo: There may be a corner case when SSR happens back to back during
3313 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303314 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303315 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303316 }
3317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 pthread_mutex_unlock(&out->lock);
3319
3320 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003321 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003322 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303323 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303324 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303325 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303326 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303327 out->standby = true;
3328 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303330 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3331 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3332 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 }
3334 return bytes;
3335}
3336
3337static int out_get_render_position(const struct audio_stream_out *stream,
3338 uint32_t *dsp_frames)
3339{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303341 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003342
3343 if (dsp_frames == NULL)
3344 return -EINVAL;
3345
3346 *dsp_frames = 0;
3347 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003348 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303349
3350 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3351 * this operation and adev_close_output_stream(where out gets reset).
3352 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303353 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303354 *dsp_frames = get_actual_pcm_frames_rendered(out);
3355 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3356 return 0;
3357 }
3358
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003359 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303360 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303361 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003362 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303363 if (ret < 0)
3364 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003365 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303366 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003367 }
3368 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303369 if (-ENETRESET == ret) {
3370 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3371 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3372 return -EINVAL;
3373 } else if(ret < 0) {
3374 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3375 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303376 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3377 /*
3378 * Handle corner case where compress session is closed during SSR
3379 * and timestamp is queried
3380 */
3381 ALOGE(" ERROR: sound card not active, return error");
3382 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303383 } else {
3384 return 0;
3385 }
Zhou Song32a556e2015-05-05 10:46:56 +08003386 } else if (audio_is_linear_pcm(out->format)) {
3387 *dsp_frames = out->written;
3388 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003389 } else
3390 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391}
3392
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003393static int out_add_audio_effect(const struct audio_stream *stream __unused,
3394 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395{
3396 return 0;
3397}
3398
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003399static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3400 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401{
3402 return 0;
3403}
3404
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003405static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3406 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407{
3408 return -EINVAL;
3409}
3410
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003411static int out_get_presentation_position(const struct audio_stream_out *stream,
3412 uint64_t *frames, struct timespec *timestamp)
3413{
3414 struct stream_out *out = (struct stream_out *)stream;
3415 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003416 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003417
Ashish Jain5106d362016-05-11 19:23:33 +05303418 /* below piece of code is not guarded against any lock because audioFliner serializes
3419 * this operation and adev_close_output_stream( where out gets reset).
3420 */
3421 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303422 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303423 *frames = get_actual_pcm_frames_rendered(out);
3424 /* this is the best we can do */
3425 clock_gettime(CLOCK_MONOTONIC, timestamp);
3426 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3427 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3428 return 0;
3429 }
3430
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003431 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003432
Ashish Jain5106d362016-05-11 19:23:33 +05303433 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3434 ret = compress_get_tstamp(out->compr, &dsp_frames,
3435 &out->sample_rate);
3436 ALOGVV("%s rendered frames %ld sample_rate %d",
3437 __func__, dsp_frames, out->sample_rate);
3438 *frames = dsp_frames;
3439 if (ret < 0)
3440 ret = -errno;
3441 if (-ENETRESET == ret) {
3442 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3443 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3444 ret = -EINVAL;
3445 } else
3446 ret = 0;
3447 /* this is the best we can do */
3448 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003449 } else {
3450 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003451 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003452 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3453 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003454 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003455 // This adjustment accounts for buffering after app processor.
3456 // It is based on estimated DSP latency per use case, rather than exact.
3457 signed_frames -=
3458 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3459
Eric Laurent949a0892013-09-20 09:20:13 -07003460 // It would be unusual for this value to be negative, but check just in case ...
3461 if (signed_frames >= 0) {
3462 *frames = signed_frames;
3463 ret = 0;
3464 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003465 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303466 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3467 *frames = out->written;
3468 clock_gettime(CLOCK_MONOTONIC, timestamp);
3469 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003470 }
3471 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003472 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003473 return ret;
3474}
3475
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003476static int out_set_callback(struct audio_stream_out *stream,
3477 stream_callback_t callback, void *cookie)
3478{
3479 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003480 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003481
3482 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003483 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003484 out->client_callback = callback;
3485 out->client_cookie = cookie;
3486 if (out->adsp_hdlr_stream_handle) {
3487 ret = audio_extn_adsp_hdlr_stream_set_callback(
3488 out->adsp_hdlr_stream_handle,
3489 callback,
3490 cookie);
3491 if (ret)
3492 ALOGW("%s:adsp hdlr callback registration failed %d",
3493 __func__, ret);
3494 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003495 pthread_mutex_unlock(&out->lock);
3496 return 0;
3497}
3498
3499static int out_pause(struct audio_stream_out* stream)
3500{
3501 struct stream_out *out = (struct stream_out *)stream;
3502 int status = -ENOSYS;
3503 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003504 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003505 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003506 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003507 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303508 struct audio_device *adev = out->dev;
3509 int snd_scard_state = get_snd_card_state(adev);
3510
3511 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3512 status = compress_pause(out->compr);
3513
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003514 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003515
Mingming Yin21854652016-04-13 11:54:02 -07003516 if (audio_extn_passthru_is_active()) {
3517 ALOGV("offload use case, pause passthru");
3518 audio_extn_passthru_on_pause(out);
3519 }
3520
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303521 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003522 audio_extn_dts_notify_playback_state(out->usecase, 0,
3523 out->sample_rate, popcount(out->channel_mask),
3524 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525 }
3526 pthread_mutex_unlock(&out->lock);
3527 }
3528 return status;
3529}
3530
3531static int out_resume(struct audio_stream_out* stream)
3532{
3533 struct stream_out *out = (struct stream_out *)stream;
3534 int status = -ENOSYS;
3535 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003536 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003537 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003538 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003539 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303541 struct audio_device *adev = out->dev;
3542 int snd_scard_state = get_snd_card_state(adev);
3543
Mingming Yin21854652016-04-13 11:54:02 -07003544 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3545 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3546 pthread_mutex_lock(&out->dev->lock);
3547 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003548 pthread_mutex_unlock(&out->dev->lock);
3549 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303550 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003551 }
3552 if (!status) {
3553 out->offload_state = OFFLOAD_STATE_PLAYING;
3554 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303555 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003556 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3557 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 }
3559 pthread_mutex_unlock(&out->lock);
3560 }
3561 return status;
3562}
3563
3564static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3565{
3566 struct stream_out *out = (struct stream_out *)stream;
3567 int status = -ENOSYS;
3568 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003569 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003570 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003571 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3572 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3573 else
3574 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3575 pthread_mutex_unlock(&out->lock);
3576 }
3577 return status;
3578}
3579
3580static int out_flush(struct audio_stream_out* stream)
3581{
3582 struct stream_out *out = (struct stream_out *)stream;
3583 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003584 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003585 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003586 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003587 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3588 stop_compressed_output_l(out);
3589 out->written = 0;
3590 } else {
3591 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3592 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003593 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003594 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003595 return 0;
3596 }
3597 return -ENOSYS;
3598}
3599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600/** audio_stream_in implementation **/
3601static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3602{
3603 struct stream_in *in = (struct stream_in *)stream;
3604
3605 return in->config.rate;
3606}
3607
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003608static int in_set_sample_rate(struct audio_stream *stream __unused,
3609 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610{
3611 return -ENOSYS;
3612}
3613
3614static size_t in_get_buffer_size(const struct audio_stream *stream)
3615{
3616 struct stream_in *in = (struct stream_in *)stream;
3617
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003618 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3619 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003620 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3621 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303622 else if(audio_extn_cin_attached_usecase(in->usecase))
3623 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003624
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003625 return in->config.period_size * in->af_period_multiplier *
3626 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627}
3628
3629static uint32_t in_get_channels(const struct audio_stream *stream)
3630{
3631 struct stream_in *in = (struct stream_in *)stream;
3632
3633 return in->channel_mask;
3634}
3635
3636static audio_format_t in_get_format(const struct audio_stream *stream)
3637{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003638 struct stream_in *in = (struct stream_in *)stream;
3639
3640 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641}
3642
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003643static int in_set_format(struct audio_stream *stream __unused,
3644 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645{
3646 return -ENOSYS;
3647}
3648
3649static int in_standby(struct audio_stream *stream)
3650{
3651 struct stream_in *in = (struct stream_in *)stream;
3652 struct audio_device *adev = in->dev;
3653 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303654 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3655 stream, in->usecase, use_case_table[in->usecase]);
3656
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003657 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003658 if (!in->standby && in->is_st_session) {
3659 ALOGD("%s: sound trigger pcm stop lab", __func__);
3660 audio_extn_sound_trigger_stop_lab(in);
3661 in->standby = 1;
3662 }
3663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003665 if (adev->adm_deregister_stream)
3666 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3667
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003668 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003670 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3671 voice_extn_compress_voip_close_input_stream(stream);
3672 ALOGD("VOIP input entered standby");
3673 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303674 if (audio_extn_cin_attached_usecase(in->usecase))
3675 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003676 if (in->pcm) {
3677 pcm_close(in->pcm);
3678 in->pcm = NULL;
3679 }
3680 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003681 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003682 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 }
3684 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003685 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 return status;
3687}
3688
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003689static int in_dump(const struct audio_stream *stream __unused,
3690 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691{
3692 return 0;
3693}
3694
3695static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3696{
3697 struct stream_in *in = (struct stream_in *)stream;
3698 struct audio_device *adev = in->dev;
3699 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003701 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303703 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 parms = str_parms_create_str(kvpairs);
3705
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303706 if (!parms)
3707 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003708 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003709 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003710
3711 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3712 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713 val = atoi(value);
3714 /* no audio source uses val == 0 */
3715 if ((in->source != val) && (val != 0)) {
3716 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003717 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3718 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3719 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003720 (in->config.rate == 8000 || in->config.rate == 16000 ||
3721 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003722 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003723 err = voice_extn_compress_voip_open_input_stream(in);
3724 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003725 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003726 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003727 }
3728 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 }
3730 }
3731
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003732 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3733 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003735 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 in->device = val;
3737 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003738 if (!in->standby && !in->is_st_session) {
3739 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003740 if (adev->adm_on_routing_change)
3741 adev->adm_on_routing_change(adev->adm_data,
3742 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003743 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 }
3746 }
3747
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303748 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3749 if (err >= 0) {
3750 strlcpy(in->profile, value, sizeof(in->profile));
3751 ALOGV("updating stream profile with value '%s'", in->profile);
3752 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3753 &adev->streams_input_cfg_list,
3754 in->device, in->flags, in->format,
3755 in->sample_rate, in->bit_width,
3756 in->profile, &in->app_type_cfg);
3757 }
3758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003760 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761
3762 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303763error:
Eric Laurent994a6932013-07-17 11:51:42 -07003764 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 return ret;
3766}
3767
3768static char* in_get_parameters(const struct audio_stream *stream,
3769 const char *keys)
3770{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003771 struct stream_in *in = (struct stream_in *)stream;
3772 struct str_parms *query = str_parms_create_str(keys);
3773 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003774 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003775
3776 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003777 if (reply) {
3778 str_parms_destroy(reply);
3779 }
3780 if (query) {
3781 str_parms_destroy(query);
3782 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003783 ALOGE("in_get_parameters: failed to create query or reply");
3784 return NULL;
3785 }
3786
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003787 ALOGV("%s: enter: keys - %s", __func__, keys);
3788
3789 voice_extn_in_get_parameters(in, query, reply);
3790
3791 str = str_parms_to_str(reply);
3792 str_parms_destroy(query);
3793 str_parms_destroy(reply);
3794
3795 ALOGV("%s: exit: returns - %s", __func__, str);
3796 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797}
3798
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003799static int in_set_gain(struct audio_stream_in *stream __unused,
3800 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801{
3802 return 0;
3803}
3804
3805static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3806 size_t bytes)
3807{
3808 struct stream_in *in = (struct stream_in *)stream;
3809 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303810 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303811 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303812 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003814 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303815
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003816 if (in->is_st_session) {
3817 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3818 /* Read from sound trigger HAL */
3819 audio_extn_sound_trigger_read(in, buffer, bytes);
3820 pthread_mutex_unlock(&in->lock);
3821 return bytes;
3822 }
3823
Ashish Jainbbce4322016-02-16 13:25:27 +05303824 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003825 ALOGD(" %s: sound card is not active/SSR state", __func__);
3826 ret= -EIO;;
3827 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303828 }
3829
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003831 pthread_mutex_lock(&adev->lock);
3832 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3833 ret = voice_extn_compress_voip_start_input_stream(in);
3834 else
3835 ret = start_input_stream(in);
3836 pthread_mutex_unlock(&adev->lock);
3837 if (ret != 0) {
3838 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 }
3840 in->standby = 0;
3841 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003843 // what's the duration requested by the client?
3844 long ns = 0;
3845
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303846 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003847 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3848 in->config.rate;
3849
3850 request_in_focus(in, ns);
3851 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003852
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303853 if (audio_extn_cin_attached_usecase(in->usecase)) {
3854 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3855 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303856 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003857 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303858 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003859 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003860 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003861 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303862 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003863 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303864 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3865 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3866 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3867 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303868 ret = -EINVAL;
3869 goto exit;
3870 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303871 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303872 ret = -errno;
3873 }
3874 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303875 /* bytes read is always set to bytes for non compress usecases */
3876 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 }
3878
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003879 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881 /*
3882 * Instead of writing zeroes here, we could trust the hardware
3883 * to always provide zeroes when muted.
3884 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303885 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3886 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 memset(buffer, 0, bytes);
3888
3889exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303890 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303891 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003892 if (-ENETRESET == ret)
3893 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895 pthread_mutex_unlock(&in->lock);
3896
3897 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303898 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303899 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303900 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303901 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303902 in->standby = true;
3903 }
Sharad Sangled17c9122017-03-20 15:58:52 +05303904 if (!audio_extn_cin_attached_usecase(in->usecase)) {
3905 bytes_read = bytes;
3906 memset(buffer, 0, bytes);
3907 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003909 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303910 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303911 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303913 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914}
3915
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003916static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917{
3918 return 0;
3919}
3920
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003921static int add_remove_audio_effect(const struct audio_stream *stream,
3922 effect_handle_t effect,
3923 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003925 struct stream_in *in = (struct stream_in *)stream;
3926 int status = 0;
3927 effect_descriptor_t desc;
3928
3929 status = (*effect)->get_descriptor(effect, &desc);
3930 if (status != 0)
3931 return status;
3932
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003933 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003934 pthread_mutex_lock(&in->dev->lock);
3935 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3936 in->enable_aec != enable &&
3937 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3938 in->enable_aec = enable;
3939 if (!in->standby)
3940 select_devices(in->dev, in->usecase);
3941 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003942 if (in->enable_ns != enable &&
3943 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3944 in->enable_ns = enable;
3945 if (!in->standby)
3946 select_devices(in->dev, in->usecase);
3947 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003948 pthread_mutex_unlock(&in->dev->lock);
3949 pthread_mutex_unlock(&in->lock);
3950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 return 0;
3952}
3953
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003954static int in_add_audio_effect(const struct audio_stream *stream,
3955 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956{
Eric Laurent994a6932013-07-17 11:51:42 -07003957 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003958 return add_remove_audio_effect(stream, effect, true);
3959}
3960
3961static int in_remove_audio_effect(const struct audio_stream *stream,
3962 effect_handle_t effect)
3963{
Eric Laurent994a6932013-07-17 11:51:42 -07003964 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003965 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966}
3967
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303968int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969 audio_io_handle_t handle,
3970 audio_devices_t devices,
3971 audio_output_flags_t flags,
3972 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003973 struct audio_stream_out **stream_out,
3974 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975{
3976 struct audio_device *adev = (struct audio_device *)dev;
3977 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303978 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003979 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003980 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303983
3984 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3985 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003986 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303987 return -EINVAL;
3988 }
3989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003990 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3991
Mingming Yin3a941d42016-02-17 18:08:05 -08003992 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3993 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303994 devices, flags, &out->stream);
3995
3996
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003997 if (!out) {
3998 return -ENOMEM;
3999 }
4000
Haynes Mathew George204045b2015-02-25 20:32:03 -08004001 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004002 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004003 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005 if (devices == AUDIO_DEVICE_NONE)
4006 devices = AUDIO_DEVICE_OUT_SPEAKER;
4007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 out->flags = flags;
4009 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004010 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004011 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004012 out->sample_rate = config->sample_rate;
4013 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4014 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004015 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004016 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004017 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304018 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004019
Mingming Yin3a941d42016-02-17 18:08:05 -08004020 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4021 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4022 pthread_mutex_lock(&adev->lock);
4023 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4024 ret = read_hdmi_sink_caps(out);
4025 pthread_mutex_unlock(&adev->lock);
4026 if (ret != 0) {
4027 if (ret == -ENOSYS) {
4028 /* ignore and go with default */
4029 ret = 0;
4030 } else {
4031 ALOGE("error reading hdmi sink caps");
4032 goto error_open;
4033 }
4034 }
4035 }
4036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304038 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004039 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004040 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004041 ret = voice_extn_compress_voip_open_output_stream(out);
4042 if (ret != 0) {
4043 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4044 __func__, ret);
4045 goto error_open;
4046 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004047 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304048 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004049
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004050 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4051 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4052 ALOGE("%s: Unsupported Offload information", __func__);
4053 ret = -EINVAL;
4054 goto error_open;
4055 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004056
Mingming Yin3a941d42016-02-17 18:08:05 -08004057 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004058 if(config->offload_info.format == 0)
4059 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004060 if (config->offload_info.sample_rate == 0)
4061 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004062 }
4063
Mingming Yin90310102013-11-13 16:57:00 -08004064 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304065 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004066 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004067 ret = -EINVAL;
4068 goto error_open;
4069 }
4070
4071 out->compr_config.codec = (struct snd_codec *)
4072 calloc(1, sizeof(struct snd_codec));
4073
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004074 if (!out->compr_config.codec) {
4075 ret = -ENOMEM;
4076 goto error_open;
4077 }
4078
Dhananjay Kumarac341582017-02-23 23:42:25 +05304079 out->stream.pause = out_pause;
4080 out->stream.resume = out_resume;
4081 out->stream.flush = out_flush;
4082 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004083 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004084 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304085 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004086 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304087 } else {
4088 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4089 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004090 }
vivek mehta446c3962015-09-14 10:57:35 -07004091
4092 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004093 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4094 config->format == 0 && config->sample_rate == 0 &&
4095 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004096 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004097 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4098 } else {
4099 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4100 ret = -EEXIST;
4101 goto error_open;
4102 }
vivek mehta446c3962015-09-14 10:57:35 -07004103 }
4104
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004105 if (config->offload_info.channel_mask)
4106 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004107 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004108 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004109 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004110 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304111 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004112 ret = -EINVAL;
4113 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004114 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004115
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004116 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004117 out->sample_rate = config->offload_info.sample_rate;
4118
Mingming Yin3ee55c62014-08-04 14:23:35 -07004119 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004120
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304121 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4122 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4123 audio_extn_dolby_send_ddp_endp_params(adev);
4124 audio_extn_dolby_set_dmid(adev);
4125 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004126
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004127 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004128 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004129 out->compr_config.codec->bit_rate =
4130 config->offload_info.bit_rate;
4131 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304132 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004133 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304134 /* Update bit width only for non passthrough usecases.
4135 * For passthrough usecases, the output will always be opened @16 bit
4136 */
4137 if (!audio_extn_passthru_is_passthrough_stream(out))
4138 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304139
4140 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4141 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4142 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4143
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004144 /*TODO: Do we need to change it for passthrough */
4145 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004146
Manish Dewangana6fc5442015-08-24 20:30:31 +05304147 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4148 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304149 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304150 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304151 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4152 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304153
4154 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4155 AUDIO_FORMAT_PCM) {
4156
4157 /*Based on platform support, configure appropriate alsa format for corresponding
4158 *hal input format.
4159 */
4160 out->compr_config.codec->format = hal_format_to_alsa(
4161 config->offload_info.format);
4162
Ashish Jain83a6cc22016-06-28 14:34:17 +05304163 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304164 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304165 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304166
Dhananjay Kumarac341582017-02-23 23:42:25 +05304167 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304168 *hal input format and alsa format might differ based on platform support.
4169 */
4170 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304171 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304172
4173 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4174
4175 /* Check if alsa session is configured with the same format as HAL input format,
4176 * if not then derive correct fragment size needed to accomodate the
4177 * conversion of HAL input format to alsa format.
4178 */
4179 audio_extn_utils_update_direct_pcm_fragment_size(out);
4180
4181 /*if hal input and output fragment size is different this indicates HAL input format is
4182 *not same as the alsa format
4183 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304184 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304185 /*Allocate a buffer to convert input data to the alsa configured format.
4186 *size of convert buffer is equal to the size required to hold one fragment size
4187 *worth of pcm data, this is because flinger does not write more than fragment_size
4188 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304189 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4190 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304191 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4192 ret = -ENOMEM;
4193 goto error_open;
4194 }
4195 }
4196 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4197 out->compr_config.fragment_size =
4198 audio_extn_passthru_get_buffer_size(&config->offload_info);
4199 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4200 } else {
4201 out->compr_config.fragment_size =
4202 platform_get_compress_offload_buffer_size(&config->offload_info);
4203 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4204 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004205
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304206 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4207 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4208 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004209 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304210 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004211
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304212 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4213 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4214 }
4215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004216 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4217 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004218
Manish Dewangan69426c82017-01-30 17:35:36 +05304219 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4220 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4221 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4222 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4223 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4224 } else {
4225 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4226 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004227
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304228 memset(&out->channel_map_param, 0,
4229 sizeof(struct audio_out_channel_map_param));
4230
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004231 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304232 out->send_next_track_params = false;
4233 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004234 out->offload_state = OFFLOAD_STATE_IDLE;
4235 out->playback_started = 0;
4236
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004237 audio_extn_dts_create_state_notifier_node(out->usecase);
4238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004239 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4240 __func__, config->offload_info.version,
4241 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304242
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304243 /* Check if DSD audio format is supported in codec
4244 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304245 */
4246
4247 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304248 (!platform_check_codec_dsd_support(adev->platform) ||
4249 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304250 ret = -EINVAL;
4251 goto error_open;
4252 }
4253
Ashish Jain5106d362016-05-11 19:23:33 +05304254 /* Disable gapless if any of the following is true
4255 * passthrough playback
4256 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304257 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304258 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304259 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304260 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004261 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304262 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304263 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304264 check_and_set_gapless_mode(adev, false);
4265 } else
4266 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004267
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304268 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004269 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4270 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304271 if (config->format == AUDIO_FORMAT_DSD) {
4272 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4273 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4274 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004275
4276 create_offload_callback_thread(out);
4277
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004278 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304279 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004280 if (ret != 0) {
4281 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4282 __func__, ret);
4283 goto error_open;
4284 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004285 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4286 if (config->sample_rate == 0)
4287 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4288 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4289 config->sample_rate != 8000) {
4290 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4291 ret = -EINVAL;
4292 goto error_open;
4293 }
4294 out->sample_rate = config->sample_rate;
4295 out->config.rate = config->sample_rate;
4296 if (config->format == AUDIO_FORMAT_DEFAULT)
4297 config->format = AUDIO_FORMAT_PCM_16_BIT;
4298 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4299 config->format = AUDIO_FORMAT_PCM_16_BIT;
4300 ret = -EINVAL;
4301 goto error_open;
4302 }
4303 out->format = config->format;
4304 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4305 out->config = pcm_config_afe_proxy_playback;
4306 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004307 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304308 unsigned int channels = 0;
4309 /*Update config params to default if not set by the caller*/
4310 if (config->sample_rate == 0)
4311 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4312 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4313 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4314 if (config->format == AUDIO_FORMAT_DEFAULT)
4315 config->format = AUDIO_FORMAT_PCM_16_BIT;
4316
4317 channels = audio_channel_count_from_out_mask(out->channel_mask);
4318
Ashish Jain83a6cc22016-06-28 14:34:17 +05304319 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4320 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004321 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4322 out->flags);
4323 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304324 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4325 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4326 out->config = pcm_config_low_latency;
4327 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4328 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4329 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304330 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4331 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4332 if (out->config.period_size <= 0) {
4333 ALOGE("Invalid configuration period size is not valid");
4334 ret = -EINVAL;
4335 goto error_open;
4336 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304337 } else {
4338 /* primary path is the default path selected if no other outputs are available/suitable */
4339 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4340 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4341 }
4342 out->hal_ip_format = format = out->format;
4343 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4344 out->hal_op_format = pcm_format_to_hal(out->config.format);
4345 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4346 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004347 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304348 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304349 if (out->hal_ip_format != out->hal_op_format) {
4350 uint32_t buffer_size = out->config.period_size *
4351 format_to_bitwidth_table[out->hal_op_format] *
4352 out->config.channels;
4353 out->convert_buffer = calloc(1, buffer_size);
4354 if (out->convert_buffer == NULL){
4355 ALOGE("Allocation failed for convert buffer for size %d",
4356 out->compr_config.fragment_size);
4357 ret = -ENOMEM;
4358 goto error_open;
4359 }
4360 ALOGD("Convert buffer allocated of size %d", buffer_size);
4361 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004362 }
4363
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004364 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4365 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304366
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004367 /* TODO remove this hardcoding and check why width is zero*/
4368 if (out->bit_width == 0)
4369 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304370 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004371 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304372 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304373 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304374 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004375 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4376 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4377 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004378 if(adev->primary_output == NULL)
4379 adev->primary_output = out;
4380 else {
4381 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004382 ret = -EEXIST;
4383 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004384 }
4385 }
4386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 /* Check if this usecase is already existing */
4388 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004389 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4390 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004393 ret = -EEXIST;
4394 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004397 pthread_mutex_unlock(&adev->lock);
4398
4399 out->stream.common.get_sample_rate = out_get_sample_rate;
4400 out->stream.common.set_sample_rate = out_set_sample_rate;
4401 out->stream.common.get_buffer_size = out_get_buffer_size;
4402 out->stream.common.get_channels = out_get_channels;
4403 out->stream.common.get_format = out_get_format;
4404 out->stream.common.set_format = out_set_format;
4405 out->stream.common.standby = out_standby;
4406 out->stream.common.dump = out_dump;
4407 out->stream.common.set_parameters = out_set_parameters;
4408 out->stream.common.get_parameters = out_get_parameters;
4409 out->stream.common.add_audio_effect = out_add_audio_effect;
4410 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4411 out->stream.get_latency = out_get_latency;
4412 out->stream.set_volume = out_set_volume;
4413 out->stream.write = out_write;
4414 out->stream.get_render_position = out_get_render_position;
4415 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004416 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004418 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004420 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004421 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422
4423 config->format = out->stream.common.get_format(&out->stream.common);
4424 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4425 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4426
4427 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304428 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004429 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004430
4431 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4432 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4433 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004434 /* setup a channel for client <--> adsp communication for stream events */
4435 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07004436 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
4437 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004438 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4439 out->usecase, PCM_PLAYBACK);
4440 hdlr_stream_cfg.flags = out->flags;
4441 hdlr_stream_cfg.type = PCM_PLAYBACK;
4442 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4443 &hdlr_stream_cfg);
4444 if (ret) {
4445 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4446 out->adsp_hdlr_stream_handle = NULL;
4447 }
4448 }
Naresh Tanniru85819452017-05-04 18:55:45 -07004449 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
4450 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
4451 if (ret < 0) {
4452 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
4453 out->ip_hdlr_handle = NULL;
4454 }
4455 }
Eric Laurent994a6932013-07-17 11:51:42 -07004456 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004458
4459error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304460 if (out->convert_buffer)
4461 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004462 free(out);
4463 *stream_out = NULL;
4464 ALOGD("%s: exit: ret %d", __func__, ret);
4465 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466}
4467
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304468void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 struct audio_stream_out *stream)
4470{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004471 struct stream_out *out = (struct stream_out *)stream;
4472 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004473 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004474
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304475 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4476
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004477 /* close adsp hdrl session before standby */
4478 if (out->adsp_hdlr_stream_handle) {
4479 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4480 if (ret)
4481 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4482 out->adsp_hdlr_stream_handle = NULL;
4483 }
4484
Naresh Tanniru85819452017-05-04 18:55:45 -07004485 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
4486 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
4487 out->ip_hdlr_handle = NULL;
4488 }
4489
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004490 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304491 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004492 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304493 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004494 if(ret != 0)
4495 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4496 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004497 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004498 out_standby(&stream->common);
4499
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004500 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004501 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004502 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004503 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004504 if (out->compr_config.codec != NULL)
4505 free(out->compr_config.codec);
4506 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004507
Ashish Jain83a6cc22016-06-28 14:34:17 +05304508 if (out->convert_buffer != NULL) {
4509 free(out->convert_buffer);
4510 out->convert_buffer = NULL;
4511 }
4512
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004513 if (adev->voice_tx_output == out)
4514 adev->voice_tx_output = NULL;
4515
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304516 if (adev->primary_output == out)
4517 adev->primary_output = NULL;
4518
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004519 pthread_cond_destroy(&out->cond);
4520 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004521 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004522 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523}
4524
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004525static void close_compress_sessions(struct audio_device *adev)
4526{
Mingming Yin7b762e72015-03-04 13:47:32 -08004527 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304528 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004529 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004530 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304531
4532 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004533 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304534 if (is_offload_usecase(usecase->id)) {
4535 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004536 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4537 out = usecase->stream.out;
4538 pthread_mutex_unlock(&adev->lock);
4539 out_standby(&out->stream.common);
4540 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004541 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004542 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304543 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004544 }
4545 pthread_mutex_unlock(&adev->lock);
4546}
4547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4549{
4550 struct audio_device *adev = (struct audio_device *)dev;
4551 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004553 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004554 int ret;
4555 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004557 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304560 if (!parms)
4561 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004562 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4563 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304564 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304565 if (strstr(snd_card_status, "OFFLINE")) {
4566 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304567 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004568 //close compress sessions on OFFLINE status
4569 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304570 } else if (strstr(snd_card_status, "ONLINE")) {
4571 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304572 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004573 //send dts hpx license if enabled
4574 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304575 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304576 }
4577
4578 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004579 status = voice_set_parameters(adev, parms);
4580 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004581 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004583 status = platform_set_parameters(adev->platform, parms);
4584 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004585 goto done;
4586
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004587 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4588 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004589 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4591 adev->bluetooth_nrec = true;
4592 else
4593 adev->bluetooth_nrec = false;
4594 }
4595
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004596 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4597 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4599 adev->screen_off = false;
4600 else
4601 adev->screen_off = true;
4602 }
4603
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004604 ret = str_parms_get_int(parms, "rotation", &val);
4605 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004606 bool reverse_speakers = false;
4607 switch(val) {
4608 // FIXME: note that the code below assumes that the speakers are in the correct placement
4609 // relative to the user when the device is rotated 90deg from its default rotation. This
4610 // assumption is device-specific, not platform-specific like this code.
4611 case 270:
4612 reverse_speakers = true;
4613 break;
4614 case 0:
4615 case 90:
4616 case 180:
4617 break;
4618 default:
4619 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004620 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004621 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004622 if (status == 0) {
4623 if (adev->speaker_lr_swap != reverse_speakers) {
4624 adev->speaker_lr_swap = reverse_speakers;
4625 // only update the selected device if there is active pcm playback
4626 struct audio_usecase *usecase;
4627 struct listnode *node;
4628 list_for_each(node, &adev->usecase_list) {
4629 usecase = node_to_item(node, struct audio_usecase, list);
4630 if (usecase->type == PCM_PLAYBACK) {
4631 select_devices(adev, usecase->id);
4632 break;
4633 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004634 }
4635 }
4636 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004637 }
4638
Mingming Yin514a8bc2014-07-29 15:22:21 -07004639 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4640 if (ret >= 0) {
4641 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4642 adev->bt_wb_speech_enabled = true;
4643 else
4644 adev->bt_wb_speech_enabled = false;
4645 }
4646
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004647 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4648 if (ret >= 0) {
4649 val = atoi(value);
4650 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004651 ALOGV("cache new ext disp type and edid");
4652 ret = platform_get_ext_disp_type(adev->platform);
4653 if (ret < 0) {
4654 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004655 status = ret;
4656 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004657 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004658 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004659 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004660 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004661 /*
4662 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4663 * Per AudioPolicyManager, USB device is higher priority than WFD.
4664 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4665 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4666 * starting voice call on USB
4667 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004668 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4669 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004670 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4671 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004672 }
vivek mehta344576a2016-04-12 18:56:03 -07004673 ALOGV("detected USB connect .. disable proxy");
4674 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004675 }
4676 }
4677
4678 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4679 if (ret >= 0) {
4680 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004681 /*
4682 * The HDMI / Displayport disconnect handling has been moved to
4683 * audio extension to ensure that its parameters are not
4684 * invalidated prior to updating sysfs of the disconnect event
4685 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4686 */
4687 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004688 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004689 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4690 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304691 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4692 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004693 }
vivek mehta344576a2016-04-12 18:56:03 -07004694 ALOGV("detected USB disconnect .. enable proxy");
4695 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004696 }
4697 }
4698
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304699 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4700 if (ret >= 0) {
4701 struct audio_usecase *usecase;
4702 struct listnode *node;
4703 list_for_each(node, &adev->usecase_list) {
4704 usecase = node_to_item(node, struct audio_usecase, list);
4705 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004706 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304707 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08004708
4709 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304710 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08004711 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304712 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304713 //force device switch to re configure encoder
4714 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304715 audio_extn_a2dp_set_handoff_mode(false);
4716 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304717 break;
4718 }
4719 }
4720 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004721
4722 //handle vr audio setparam
4723 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4724 value, sizeof(value));
4725 if (ret >= 0) {
4726 ALOGI("Setting vr mode to be %s", value);
4727 if (!strncmp(value, "true", 4)) {
4728 adev->vr_audio_mode_enabled = true;
4729 ALOGI("Setting vr mode to true");
4730 } else if (!strncmp(value, "false", 5)) {
4731 adev->vr_audio_mode_enabled = false;
4732 ALOGI("Setting vr mode to false");
4733 } else {
4734 ALOGI("wrong vr mode set");
4735 }
4736 }
4737
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304738 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004739done:
4740 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004741 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304742error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004743 ALOGV("%s: exit with code(%d)", __func__, status);
4744 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004745}
4746
4747static char* adev_get_parameters(const struct audio_hw_device *dev,
4748 const char *keys)
4749{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004750 struct audio_device *adev = (struct audio_device *)dev;
4751 struct str_parms *reply = str_parms_create();
4752 struct str_parms *query = str_parms_create_str(keys);
4753 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304754 char value[256] = {0};
4755 int ret = 0;
4756
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004757 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004758 if (reply) {
4759 str_parms_destroy(reply);
4760 }
4761 if (query) {
4762 str_parms_destroy(query);
4763 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004764 ALOGE("adev_get_parameters: failed to create query or reply");
4765 return NULL;
4766 }
4767
Naresh Tannirud7205b62014-06-20 02:54:48 +05304768 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4769 sizeof(value));
4770 if (ret >=0) {
4771 int val = 1;
4772 pthread_mutex_lock(&adev->snd_card_status.lock);
4773 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4774 val = 0;
4775 pthread_mutex_unlock(&adev->snd_card_status.lock);
4776 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4777 goto exit;
4778 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004779 //handle vr audio getparam
4780
4781 ret = str_parms_get_str(query,
4782 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4783 value, sizeof(value));
4784
4785 if (ret >= 0) {
4786 bool vr_audio_enabled = false;
4787 pthread_mutex_lock(&adev->lock);
4788 vr_audio_enabled = adev->vr_audio_mode_enabled;
4789 pthread_mutex_unlock(&adev->lock);
4790
4791 ALOGI("getting vr mode to %d", vr_audio_enabled);
4792
4793 if (vr_audio_enabled) {
4794 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4795 "true");
4796 goto exit;
4797 } else {
4798 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4799 "false");
4800 goto exit;
4801 }
4802 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004803
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004804 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004805 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004806 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004807 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304808 pthread_mutex_unlock(&adev->lock);
4809
Naresh Tannirud7205b62014-06-20 02:54:48 +05304810exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004811 str = str_parms_to_str(reply);
4812 str_parms_destroy(query);
4813 str_parms_destroy(reply);
4814
4815 ALOGV("%s: exit: returns - %s", __func__, str);
4816 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817}
4818
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004819static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820{
4821 return 0;
4822}
4823
4824static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4825{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004826 int ret;
4827 struct audio_device *adev = (struct audio_device *)dev;
4828 pthread_mutex_lock(&adev->lock);
4829 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004830 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004831 pthread_mutex_unlock(&adev->lock);
4832 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004833}
4834
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004835static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4836 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837{
4838 return -ENOSYS;
4839}
4840
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004841static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4842 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004843{
4844 return -ENOSYS;
4845}
4846
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004847static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4848 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849{
4850 return -ENOSYS;
4851}
4852
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004853static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4854 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855{
4856 return -ENOSYS;
4857}
4858
4859static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4860{
4861 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863 pthread_mutex_lock(&adev->lock);
4864 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004865 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004866 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004867 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004868 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004869 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004870 adev->current_call_output = NULL;
4871 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004872 }
4873 pthread_mutex_unlock(&adev->lock);
4874 return 0;
4875}
4876
4877static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4878{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004879 int ret;
4880
4881 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004882 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004883 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4884 pthread_mutex_unlock(&adev->lock);
4885
4886 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887}
4888
4889static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4890{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004891 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004892 return 0;
4893}
4894
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004895static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004896 const struct audio_config *config)
4897{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004898 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004899
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004900 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4901 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902}
4903
4904static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004905 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906 audio_devices_t devices,
4907 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004908 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304909 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004910 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004911 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912{
4913 struct audio_device *adev = (struct audio_device *)dev;
4914 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004915 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004916 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004917 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304918 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304921 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4922 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004923 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304924 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925
4926 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004927
4928 if (!in) {
4929 ALOGE("failed to allocate input stream");
4930 return -ENOMEM;
4931 }
4932
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304933 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304934 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4935 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004936 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004937 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939 in->stream.common.get_sample_rate = in_get_sample_rate;
4940 in->stream.common.set_sample_rate = in_set_sample_rate;
4941 in->stream.common.get_buffer_size = in_get_buffer_size;
4942 in->stream.common.get_channels = in_get_channels;
4943 in->stream.common.get_format = in_get_format;
4944 in->stream.common.set_format = in_set_format;
4945 in->stream.common.standby = in_standby;
4946 in->stream.common.dump = in_dump;
4947 in->stream.common.set_parameters = in_set_parameters;
4948 in->stream.common.get_parameters = in_get_parameters;
4949 in->stream.common.add_audio_effect = in_add_audio_effect;
4950 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4951 in->stream.set_gain = in_set_gain;
4952 in->stream.read = in_read;
4953 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4954
4955 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004956 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004958 in->standby = 1;
4959 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004960 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004961 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004962
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304963 in->usecase = USECASE_AUDIO_RECORD;
4964 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4965 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4966 is_low_latency = true;
4967#if LOW_LATENCY_CAPTURE_USE_CASE
4968 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4969#endif
4970 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4971 }
4972
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004973 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004974 if (in->realtime) {
4975 in->config = pcm_config_audio_capture_rt;
4976 in->sample_rate = in->config.rate;
4977 in->af_period_multiplier = af_period_multiplier;
4978 } else {
4979 in->config = pcm_config_audio_capture;
4980 in->config.rate = config->sample_rate;
4981 in->sample_rate = config->sample_rate;
4982 in->af_period_multiplier = 1;
4983 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304984 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004985
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304986 /* restrict 24 bit capture for unprocessed source only
4987 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4988 */
4989 if (config->format == AUDIO_FORMAT_DEFAULT) {
4990 config->format = AUDIO_FORMAT_PCM_16_BIT;
4991 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4992 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4993 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4994 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4995 bool ret_error = false;
4996 in->bit_width = 24;
4997 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4998 from HAL is 24_packed and 8_24
4999 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5000 24_packed return error indicating supported format is 24_packed
5001 *> In case of any other source requesting 24 bit or float return error
5002 indicating format supported is 16 bit only.
5003
5004 on error flinger will retry with supported format passed
5005 */
5006 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5007 (source != AUDIO_SOURCE_CAMCORDER)) {
5008 config->format = AUDIO_FORMAT_PCM_16_BIT;
5009 if (config->sample_rate > 48000)
5010 config->sample_rate = 48000;
5011 ret_error = true;
5012 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5013 in->config.format = PCM_FORMAT_S24_3LE;
5014 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5015 in->config.format = PCM_FORMAT_S24_LE;
5016 } else {
5017 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5018 ret_error = true;
5019 }
5020
5021 if (ret_error) {
5022 ret = -EINVAL;
5023 goto err_open;
5024 }
5025 }
5026
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305027 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305028 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5029 (adev->mode != AUDIO_MODE_IN_CALL)) {
5030 ret = -EINVAL;
5031 goto err_open;
5032 }
5033
5034 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5035 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005036 if (config->sample_rate == 0)
5037 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5038 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5039 config->sample_rate != 8000) {
5040 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5041 ret = -EINVAL;
5042 goto err_open;
5043 }
5044 if (config->format == AUDIO_FORMAT_DEFAULT)
5045 config->format = AUDIO_FORMAT_PCM_16_BIT;
5046 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5047 config->format = AUDIO_FORMAT_PCM_16_BIT;
5048 ret = -EINVAL;
5049 goto err_open;
5050 }
5051
5052 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5053 in->config = pcm_config_afe_proxy_record;
5054 in->config.channels = channel_count;
5055 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305056 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305057 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5058 in, config, &channel_mask_updated)) {
5059 if (channel_mask_updated == true) {
5060 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5061 __func__, config->channel_mask);
5062 ret = -EINVAL;
5063 goto err_open;
5064 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305065 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005066 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005067 audio_extn_compr_cap_format_supported(config->format) &&
5068 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005069 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305070 } else if (audio_extn_cin_applicable_stream(in)) {
5071 ret = audio_extn_cin_configure_input_stream(in);
5072 if (ret)
5073 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005074 } else {
5075 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005076 if (!in->realtime) {
5077 in->format = config->format;
5078 frame_size = audio_stream_in_frame_size(&in->stream);
5079 buffer_size = get_input_buffer_size(config->sample_rate,
5080 config->format,
5081 channel_count,
5082 is_low_latency);
5083 in->config.period_size = buffer_size / frame_size;
5084 }
5085
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005086 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005087 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005088 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005089 (in->config.rate == 8000 || in->config.rate == 16000 ||
5090 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005091 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5092 voice_extn_compress_voip_open_input_stream(in);
5093 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005094 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005095
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305096 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5097 &adev->streams_input_cfg_list,
5098 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305099 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305100
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005101 /* This stream could be for sound trigger lab,
5102 get sound trigger pcm if present */
5103 audio_extn_sound_trigger_check_and_get_session(in);
5104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005105 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005106 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005107 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108
5109err_open:
5110 free(in);
5111 *stream_in = NULL;
5112 return ret;
5113}
5114
5115static void adev_close_input_stream(struct audio_hw_device *dev,
5116 struct audio_stream_in *stream)
5117{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005118 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005119 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005120 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305121
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305122 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005123
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305124 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005125 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305126
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005127 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305128 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005129 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305130 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005131 if (ret != 0)
5132 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5133 __func__, ret);
5134 } else
5135 in_standby(&stream->common);
5136
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005137 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005138 audio_extn_ssr_deinit();
5139 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005140
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305141 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005142 audio_extn_compr_cap_format_supported(in->config.format))
5143 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305144
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305145 if (audio_extn_cin_attached_usecase(in->usecase))
5146 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005147
Mingming Yinfd7607b2016-01-22 12:48:44 -08005148 if (in->is_st_session) {
5149 ALOGV("%s: sound trigger pcm stop lab", __func__);
5150 audio_extn_sound_trigger_stop_lab(in);
5151 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005152 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005153 return;
5154}
5155
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005156static int adev_dump(const audio_hw_device_t *device __unused,
5157 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158{
5159 return 0;
5160}
5161
5162static int adev_close(hw_device_t *device)
5163{
5164 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005165
5166 if (!adev)
5167 return 0;
5168
5169 pthread_mutex_lock(&adev_init_lock);
5170
5171 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005172 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005173 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305174 audio_extn_utils_release_streams_cfg_lists(
5175 &adev->streams_output_cfg_list,
5176 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305177 if (audio_extn_qaf_is_enabled())
5178 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005179 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005180 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005181 free(adev->snd_dev_ref_cnt);
5182 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005183 if (adev->adm_deinit)
5184 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305185 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005186 audio_extn_adsp_hdlr_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005187 free(device);
5188 adev = NULL;
5189 }
5190 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005192 return 0;
5193}
5194
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005195/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5196 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5197 * just that it _might_ work.
5198 */
5199static int period_size_is_plausible_for_low_latency(int period_size)
5200{
5201 switch (period_size) {
5202 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005203 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005204 case 240:
5205 case 320:
5206 case 480:
5207 return 1;
5208 default:
5209 return 0;
5210 }
5211}
5212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213static int adev_open(const hw_module_t *module, const char *name,
5214 hw_device_t **device)
5215{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305216 int ret;
5217
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005218 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005219 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5220
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005221 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005222 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005223 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005224 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005225 ALOGD("%s: returning existing instance of adev", __func__);
5226 ALOGD("%s: exit", __func__);
5227 pthread_mutex_unlock(&adev_init_lock);
5228 return 0;
5229 }
5230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 adev = calloc(1, sizeof(struct audio_device));
5232
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005233 if (!adev) {
5234 pthread_mutex_unlock(&adev_init_lock);
5235 return -ENOMEM;
5236 }
5237
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005238 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5239
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305240#ifdef DYNAMIC_LOG_ENABLED
5241 register_for_dynamic_logging("hal");
5242#endif
5243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005244 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5245 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5246 adev->device.common.module = (struct hw_module_t *)module;
5247 adev->device.common.close = adev_close;
5248
5249 adev->device.init_check = adev_init_check;
5250 adev->device.set_voice_volume = adev_set_voice_volume;
5251 adev->device.set_master_volume = adev_set_master_volume;
5252 adev->device.get_master_volume = adev_get_master_volume;
5253 adev->device.set_master_mute = adev_set_master_mute;
5254 adev->device.get_master_mute = adev_get_master_mute;
5255 adev->device.set_mode = adev_set_mode;
5256 adev->device.set_mic_mute = adev_set_mic_mute;
5257 adev->device.get_mic_mute = adev_get_mic_mute;
5258 adev->device.set_parameters = adev_set_parameters;
5259 adev->device.get_parameters = adev_get_parameters;
5260 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5261 adev->device.open_output_stream = adev_open_output_stream;
5262 adev->device.close_output_stream = adev_close_output_stream;
5263 adev->device.open_input_stream = adev_open_input_stream;
5264 adev->device.close_input_stream = adev_close_input_stream;
5265 adev->device.dump = adev_dump;
5266
5267 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005269 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005270 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005273 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005274 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005275 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005276 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005277 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005278 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005279 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005280 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305281 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305282 adev->perf_lock_opts[0] = 0x101;
5283 adev->perf_lock_opts[1] = 0x20E;
5284 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305285
5286 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5287 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005288 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005289 adev->platform = platform_init(adev);
5290 if (!adev->platform) {
5291 free(adev->snd_dev_ref_cnt);
5292 free(adev);
5293 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5294 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005295 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305296 pthread_mutex_destroy(&adev->lock);
5297 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005298 return -EINVAL;
5299 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005300
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305301 if (audio_extn_qaf_is_enabled()) {
5302 ret = audio_extn_qaf_init(adev);
5303 if (ret < 0) {
5304 free(adev);
5305 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5306 *device = NULL;
5307 pthread_mutex_unlock(&adev_init_lock);
5308 pthread_mutex_destroy(&adev->lock);
5309 return ret;
5310 }
5311
5312 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5313 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5314 }
5315
Naresh Tanniru4c630392014-05-12 01:05:52 +05305316 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5317
Eric Laurentc4aef752013-09-12 17:45:53 -07005318 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5319 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5320 if (adev->visualizer_lib == NULL) {
5321 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5322 } else {
5323 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5324 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005325 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005326 "visualizer_hal_start_output");
5327 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005328 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005329 "visualizer_hal_stop_output");
5330 }
5331 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305332 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005333 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005334 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005335 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005336
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005337 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5338 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5339 if (adev->offload_effects_lib == NULL) {
5340 ALOGE("%s: DLOPEN failed for %s", __func__,
5341 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5342 } else {
5343 ALOGV("%s: DLOPEN successful for %s", __func__,
5344 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5345 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305346 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005347 "offload_effects_bundle_hal_start_output");
5348 adev->offload_effects_stop_output =
5349 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5350 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005351 adev->offload_effects_set_hpx_state =
5352 (int (*)(bool))dlsym(adev->offload_effects_lib,
5353 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305354 adev->offload_effects_get_parameters =
5355 (void (*)(struct str_parms *, struct str_parms *))
5356 dlsym(adev->offload_effects_lib,
5357 "offload_effects_bundle_get_parameters");
5358 adev->offload_effects_set_parameters =
5359 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5360 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005361 }
5362 }
5363
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005364 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5365 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5366 if (adev->adm_lib == NULL) {
5367 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5368 } else {
5369 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5370 adev->adm_init = (adm_init_t)
5371 dlsym(adev->adm_lib, "adm_init");
5372 adev->adm_deinit = (adm_deinit_t)
5373 dlsym(adev->adm_lib, "adm_deinit");
5374 adev->adm_register_input_stream = (adm_register_input_stream_t)
5375 dlsym(adev->adm_lib, "adm_register_input_stream");
5376 adev->adm_register_output_stream = (adm_register_output_stream_t)
5377 dlsym(adev->adm_lib, "adm_register_output_stream");
5378 adev->adm_deregister_stream = (adm_deregister_stream_t)
5379 dlsym(adev->adm_lib, "adm_deregister_stream");
5380 adev->adm_request_focus = (adm_request_focus_t)
5381 dlsym(adev->adm_lib, "adm_request_focus");
5382 adev->adm_abandon_focus = (adm_abandon_focus_t)
5383 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005384 adev->adm_set_config = (adm_set_config_t)
5385 dlsym(adev->adm_lib, "adm_set_config");
5386 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5387 dlsym(adev->adm_lib, "adm_request_focus_v2");
5388 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5389 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5390 adev->adm_on_routing_change = (adm_on_routing_change_t)
5391 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005392 }
5393 }
5394
Mingming Yin514a8bc2014-07-29 15:22:21 -07005395 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005396 //initialize this to false for now,
5397 //this will be set to true through set param
5398 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005399
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005400 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005401 *device = &adev->device.common;
5402
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305403 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5404 &adev->streams_output_cfg_list,
5405 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005406
Kiran Kandi910e1862013-10-29 13:29:42 -07005407 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005408
5409 char value[PROPERTY_VALUE_MAX];
5410 int trial;
5411 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5412 trial = atoi(value);
5413 if (period_size_is_plausible_for_low_latency(trial)) {
5414 pcm_config_low_latency.period_size = trial;
5415 pcm_config_low_latency.start_threshold = trial / 4;
5416 pcm_config_low_latency.avail_min = trial / 4;
5417 configured_low_latency_capture_period_size = trial;
5418 }
5419 }
5420 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5421 trial = atoi(value);
5422 if (period_size_is_plausible_for_low_latency(trial)) {
5423 configured_low_latency_capture_period_size = trial;
5424 }
5425 }
5426
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005427 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5428 af_period_multiplier = atoi(value);
5429 if (af_period_multiplier < 0)
5430 af_period_multiplier = 2;
5431 else if (af_period_multiplier > 4)
5432 af_period_multiplier = 4;
5433
5434 ALOGV("new period_multiplier = %d", af_period_multiplier);
5435 }
5436
vivek mehta446c3962015-09-14 10:57:35 -07005437 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005438 pthread_mutex_unlock(&adev_init_lock);
5439
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005440 if (adev->adm_init)
5441 adev->adm_data = adev->adm_init();
5442
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305443 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305444 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005445 audio_extn_adsp_hdlr_init(adev->mixer);
Eric Laurent994a6932013-07-17 11:51:42 -07005446 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005447 return 0;
5448}
5449
5450static struct hw_module_methods_t hal_module_methods = {
5451 .open = adev_open,
5452};
5453
5454struct audio_module HAL_MODULE_INFO_SYM = {
5455 .common = {
5456 .tag = HARDWARE_MODULE_TAG,
5457 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5458 .hal_api_version = HARDWARE_HAL_API_VERSION,
5459 .id = AUDIO_HARDWARE_MODULE_ID,
5460 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005461 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005462 .methods = &hal_module_methods,
5463 },
5464};