blob: f2820a7421d2c95bf7cf1c54f46ecb1d418a40c5 [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",
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530266 /* Transcode loopback cases */
267 [USECASE_AUDIO_TRANSCODE_LOOPBACK] = "audio-transcode-loopback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700268};
269
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700270static const audio_usecase_t offload_usecases[] = {
271 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700272 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
273 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
274 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
275 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
276 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
277 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
278 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
279 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700280};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800281
282#define STRING_TO_ENUM(string) { #string, string }
283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800284struct string_to_enum {
285 const char *name;
286 uint32_t value;
287};
288
289static const struct string_to_enum out_channels_name_to_enum_table[] = {
290 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800291 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
292 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
293 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700294 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800295 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
296 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800297 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
298};
299
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700300static const struct string_to_enum out_formats_name_to_enum_table[] = {
301 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
302 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
303 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700304 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800305 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
306 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700307 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800308};
309
310//list of all supported sample rates by HDMI specification.
311static const int out_hdmi_sample_rates[] = {
312 32000, 44100, 48000, 88200, 96000, 176400, 192000,
313};
314
315static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
316 STRING_TO_ENUM(32000),
317 STRING_TO_ENUM(44100),
318 STRING_TO_ENUM(48000),
319 STRING_TO_ENUM(88200),
320 STRING_TO_ENUM(96000),
321 STRING_TO_ENUM(176400),
322 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700323};
324
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700325static struct audio_device *adev = NULL;
326static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700327static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700330
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700331static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
332 int flags __unused)
333{
334 int dir = 0;
335 switch (uc_id) {
336 case USECASE_AUDIO_RECORD_LOW_LATENCY:
337 dir = 1;
338 case USECASE_AUDIO_PLAYBACK_ULL:
339 break;
340 default:
341 return false;
342 }
343
344 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
345 PCM_PLAYBACK : PCM_CAPTURE);
346 if (adev->adm_is_noirq_avail)
347 return adev->adm_is_noirq_avail(adev->adm_data,
348 adev->snd_card, dev_id, dir);
349 return false;
350}
351
352static void register_out_stream(struct stream_out *out)
353{
354 struct audio_device *adev = out->dev;
355 if (is_offload_usecase(out->usecase) ||
356 !adev->adm_register_output_stream)
357 return;
358
359 // register stream first for backward compatibility
360 adev->adm_register_output_stream(adev->adm_data,
361 out->handle,
362 out->flags);
363
364 if (!adev->adm_set_config)
365 return;
366
367 if (out->realtime)
368 adev->adm_set_config(adev->adm_data,
369 out->handle,
370 out->pcm, &out->config);
371}
372
373static void register_in_stream(struct stream_in *in)
374{
375 struct audio_device *adev = in->dev;
376 if (!adev->adm_register_input_stream)
377 return;
378
379 adev->adm_register_input_stream(adev->adm_data,
380 in->capture_handle,
381 in->flags);
382
383 if (!adev->adm_set_config)
384 return;
385
386 if (in->realtime)
387 adev->adm_set_config(adev->adm_data,
388 in->capture_handle,
389 in->pcm,
390 &in->config);
391}
392
393static void request_out_focus(struct stream_out *out, long ns)
394{
395 struct audio_device *adev = out->dev;
396
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700397 if (adev->adm_request_focus_v2)
398 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
399 else if (adev->adm_request_focus)
400 adev->adm_request_focus(adev->adm_data, out->handle);
401}
402
403static void request_in_focus(struct stream_in *in, long ns)
404{
405 struct audio_device *adev = in->dev;
406
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700407 if (adev->adm_request_focus_v2)
408 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
409 else if (adev->adm_request_focus)
410 adev->adm_request_focus(adev->adm_data, in->capture_handle);
411}
412
413static void release_out_focus(struct stream_out *out)
414{
415 struct audio_device *adev = out->dev;
416
417 if (adev->adm_abandon_focus)
418 adev->adm_abandon_focus(adev->adm_data, out->handle);
419}
420
421static void release_in_focus(struct stream_in *in)
422{
423 struct audio_device *adev = in->dev;
424 if (adev->adm_abandon_focus)
425 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
426}
427
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530428static int parse_snd_card_status(struct str_parms *parms, int *card,
429 card_status_t *status)
430{
431 char value[32]={0};
432 char state[32]={0};
433
434 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
435 if (ret < 0)
436 return -1;
437
438 // sscanf should be okay as value is of max length 32.
439 // same as sizeof state.
440 if (sscanf(value, "%d,%s", card, state) < 2)
441 return -1;
442
443 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
444 CARD_STATUS_OFFLINE;
445 return 0;
446}
447
vivek mehtaa76401a2015-04-24 14:12:15 -0700448__attribute__ ((visibility ("default")))
449bool audio_hw_send_gain_dep_calibration(int level) {
450 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700451 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700452
453 pthread_mutex_lock(&adev_init_lock);
454
455 if (adev != NULL && adev->platform != NULL) {
456 pthread_mutex_lock(&adev->lock);
457 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700458
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530459 // cache level info for any of the use case which
460 // was not started.
461 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700462
vivek mehtaa76401a2015-04-24 14:12:15 -0700463 pthread_mutex_unlock(&adev->lock);
464 } else {
465 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
466 }
467
468 pthread_mutex_unlock(&adev_init_lock);
469
470 return ret_val;
471}
472
Ashish Jain5106d362016-05-11 19:23:33 +0530473static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
474{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800475 bool gapless_enabled = false;
476 const char *mixer_ctl_name = "Compress Gapless Playback";
477 struct mixer_ctl *ctl;
478
479 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700480 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530481
482 /*Disable gapless if its AV playback*/
483 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800484
485 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
486 if (!ctl) {
487 ALOGE("%s: Could not get ctl for mixer cmd - %s",
488 __func__, mixer_ctl_name);
489 return -EINVAL;
490 }
491
492 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
493 ALOGE("%s: Could not set gapless mode %d",
494 __func__, gapless_enabled);
495 return -EINVAL;
496 }
497 return 0;
498}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700499
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700500__attribute__ ((visibility ("default")))
501int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
502 int table_size) {
503 int ret_val = 0;
504 ALOGV("%s: enter ... ", __func__);
505
506 pthread_mutex_lock(&adev_init_lock);
507 if (adev == NULL) {
508 ALOGW("%s: adev is NULL .... ", __func__);
509 goto done;
510 }
511
512 pthread_mutex_lock(&adev->lock);
513 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
514 pthread_mutex_unlock(&adev->lock);
515done:
516 pthread_mutex_unlock(&adev_init_lock);
517 ALOGV("%s: exit ... ", __func__);
518 return ret_val;
519}
520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521static bool is_supported_format(audio_format_t format)
522{
Eric Laurent86e17132013-09-12 17:49:30 -0700523 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530524 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530525 format == AUDIO_FORMAT_AAC_LC ||
526 format == AUDIO_FORMAT_AAC_HE_V1 ||
527 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530528 format == AUDIO_FORMAT_AAC_ADTS_LC ||
529 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
530 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530531 format == AUDIO_FORMAT_AAC_LATM_LC ||
532 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
533 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530534 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
535 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530536 format == AUDIO_FORMAT_PCM_FLOAT ||
537 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700538 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530539 format == AUDIO_FORMAT_AC3 ||
540 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700541 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530542 format == AUDIO_FORMAT_DTS ||
543 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800544 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530545 format == AUDIO_FORMAT_ALAC ||
546 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530547 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530548 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800549 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530550 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700551 format == AUDIO_FORMAT_APTX ||
552 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800553 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554
555 return false;
556}
557
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700558static inline bool is_mmap_usecase(audio_usecase_t uc_id)
559{
560 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
561 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
562}
563
Avinash Vaish71a8b972014-07-24 15:36:33 +0530564static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
565 struct audio_usecase *uc_info)
566{
567 struct listnode *node;
568 struct audio_usecase *usecase;
569
570 if (uc_info == NULL)
571 return -EINVAL;
572
573 /* Re-route all voice usecases on the shared backend other than the
574 specified usecase to new snd devices */
575 list_for_each(node, &adev->usecase_list) {
576 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800577 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530578 enable_audio_route(adev, usecase);
579 }
580 return 0;
581}
582
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530583static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530584{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585 ALOGV("%s", __func__);
586 audio_route_apply_and_update_path(adev->audio_route,
587 "asrc-mode");
588 adev->asrc_mode_enabled = true;
589}
590
591static void disable_asrc_mode(struct audio_device *adev)
592{
593 ALOGV("%s", __func__);
594 audio_route_reset_and_update_path(adev->audio_route,
595 "asrc-mode");
596 adev->asrc_mode_enabled = false;
597}
598
599/*
600 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
601 * 44.1 or Native DSD backends are enabled for any of current use case.
602 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
603 * - Disable current mix path use case(Headphone backend) and re-enable it with
604 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
605 * e.g. Naitve DSD or Headphone 44.1 -> + 48
606 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530607static void check_and_set_asrc_mode(struct audio_device *adev,
608 struct audio_usecase *uc_info,
609 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530610{
611 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530612 int i, num_new_devices = 0;
613 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
614 /*
615 *Split snd device for new combo use case
616 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
617 */
618 if (platform_split_snd_device(adev->platform,
619 snd_device,
620 &num_new_devices,
621 split_new_snd_devices) == 0) {
622 for (i = 0; i < num_new_devices; i++)
623 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
624 } else {
625 int new_backend_idx = platform_get_backend_index(snd_device);
626 if (((new_backend_idx == HEADPHONE_BACKEND) ||
627 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
628 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
629 !adev->asrc_mode_enabled) {
630 struct listnode *node = NULL;
631 struct audio_usecase *uc = NULL;
632 struct stream_out *curr_out = NULL;
633 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
634 int i, num_devices, ret = 0;
635 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530636
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530637 list_for_each(node, &adev->usecase_list) {
638 uc = node_to_item(node, struct audio_usecase, list);
639 curr_out = (struct stream_out*) uc->stream.out;
640 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
641 /*
642 *Split snd device for existing combo use case
643 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
644 */
645 ret = platform_split_snd_device(adev->platform,
646 uc->out_snd_device,
647 &num_devices,
648 split_snd_devices);
649 if (ret < 0 || num_devices == 0) {
650 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
651 split_snd_devices[0] = uc->out_snd_device;
652 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800653 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530654 for (i = 0; i < num_devices; i++) {
655 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
656 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
657 if((new_backend_idx == HEADPHONE_BACKEND) &&
658 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
659 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
660 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
661 __func__);
662 enable_asrc_mode(adev);
663 break;
664 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
665 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
666 (usecase_backend_idx == HEADPHONE_BACKEND)) {
667 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
668 __func__);
669 disable_audio_route(adev, uc);
670 disable_snd_device(adev, uc->out_snd_device);
671 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
672 if (new_backend_idx == DSD_NATIVE_BACKEND)
673 audio_route_apply_and_update_path(adev->audio_route,
674 "hph-true-highquality-mode");
675 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
676 (curr_out->bit_width >= 24))
677 audio_route_apply_and_update_path(adev->audio_route,
678 "hph-highquality-mode");
679 enable_asrc_mode(adev);
680 enable_snd_device(adev, uc->out_snd_device);
681 enable_audio_route(adev, uc);
682 break;
683 }
684 }
685 // reset split devices count
686 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800687 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530688 if (adev->asrc_mode_enabled)
689 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530690 }
691 }
692 }
693}
694
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700695int pcm_ioctl(struct pcm *pcm, int request, ...)
696{
697 va_list ap;
698 void * arg;
699 int pcm_fd = *(int*)pcm;
700
701 va_start(ap, request);
702 arg = va_arg(ap, void *);
703 va_end(ap);
704
705 return ioctl(pcm_fd, request, arg);
706}
707
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700708int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700709 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800710{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700712 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +0530713 struct stream_out *out = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800714
715 if (usecase == NULL)
716 return -EINVAL;
717
718 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
719
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800720 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800722 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700723 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800724
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800725#ifdef DS1_DOLBY_DAP_ENABLED
726 audio_extn_dolby_set_dmid(adev);
727 audio_extn_dolby_set_endpoint(adev);
728#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700729 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700730 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530731 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700732 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530733 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +0530734 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
735 out = usecase->stream.out;
736 if (out && out->compr)
737 audio_extn_utils_compress_set_clk_rec_mode(usecase);
738 }
739
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800740 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700741 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700742 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700743 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744 ALOGV("%s: exit", __func__);
745 return 0;
746}
747
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700748int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700749 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700752 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800753
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530754 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800755 return -EINVAL;
756
757 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700758 if (usecase->type == PCM_CAPTURE)
759 snd_device = usecase->in_snd_device;
760 else
761 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800762 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700763 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700764 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700765 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700766 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530767 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800768 ALOGV("%s: exit", __func__);
769 return 0;
770}
771
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700772int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700773 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800774{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530775 int i, num_devices = 0;
776 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700777 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
778
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800779 if (snd_device < SND_DEVICE_MIN ||
780 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800781 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800782 return -EINVAL;
783 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700784
785 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700786
787 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
788 ALOGE("%s: Invalid sound device returned", __func__);
789 return -EINVAL;
790 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700791 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700792 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700793 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700794 return 0;
795 }
796
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530797
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700798 if (audio_extn_spkr_prot_is_enabled())
799 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700800
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800801 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
802 audio_extn_spkr_prot_is_enabled()) {
803 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700804 adev->snd_dev_ref_cnt[snd_device]--;
805 return -EINVAL;
806 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200807 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800808 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800809 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200810 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800811 return -EINVAL;
812 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700813 } else if (platform_split_snd_device(adev->platform,
814 snd_device,
815 &num_devices,
816 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530817 for (i = 0; i < num_devices; i++) {
818 enable_snd_device(adev, new_snd_devices[i]);
819 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800820 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700821 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530822
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530823
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530824 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
825 (audio_extn_a2dp_start_playback() < 0)) {
826 ALOGE(" fail to configure A2dp control path ");
827 return -EINVAL;
828 }
829
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700830 /* due to the possibility of calibration overwrite between listen
831 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700832 audio_extn_sound_trigger_update_device_status(snd_device,
833 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530834 audio_extn_listen_update_device_status(snd_device,
835 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700836 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700837 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700838 audio_extn_sound_trigger_update_device_status(snd_device,
839 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530840 audio_extn_listen_update_device_status(snd_device,
841 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700842 return -EINVAL;
843 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300844 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700845 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530846
847 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
848 !adev->native_playback_enabled &&
849 audio_is_true_native_stream_active(adev)) {
850 ALOGD("%s: %d: napb: enabling native mode in hardware",
851 __func__, __LINE__);
852 audio_route_apply_and_update_path(adev->audio_route,
853 "true-native-mode");
854 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530855 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800857 return 0;
858}
859
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700860int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700861 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530863 int i, num_devices = 0;
864 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700865 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
866
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800867 if (snd_device < SND_DEVICE_MIN ||
868 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800869 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800870 return -EINVAL;
871 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
873 ALOGE("%s: device ref cnt is already 0", __func__);
874 return -EINVAL;
875 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700876
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700878
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700879 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
880 ALOGE("%s: Invalid sound device returned", __func__);
881 return -EINVAL;
882 }
883
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700885 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530886
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800887 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
888 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700889 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700890 } else if (platform_split_snd_device(adev->platform,
891 snd_device,
892 &num_devices,
893 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530894 for (i = 0; i < num_devices; i++) {
895 disable_snd_device(adev, new_snd_devices[i]);
896 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300897 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700898 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300899 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700900
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530901 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
902 audio_extn_a2dp_stop_playback();
903
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700904 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530905 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530906 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
907 adev->native_playback_enabled) {
908 ALOGD("%s: %d: napb: disabling native mode in hardware",
909 __func__, __LINE__);
910 audio_route_reset_and_update_path(adev->audio_route,
911 "true-native-mode");
912 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530913 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
914 adev->asrc_mode_enabled) {
915 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530916 disable_asrc_mode(adev);
917 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530918 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530919
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200920 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700921 audio_extn_sound_trigger_update_device_status(snd_device,
922 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530923 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800924 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700925 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800927 return 0;
928}
929
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700930/*
931 legend:
932 uc - existing usecase
933 new_uc - new usecase
934 d1, d11, d2 - SND_DEVICE enums
935 a1, a2 - corresponding ANDROID device enums
936 B1, B2 - backend strings
937
938case 1
939 uc->dev d1 (a1) B1
940 new_uc->dev d1 (a1), d2 (a2) B1, B2
941
942 resolution: disable and enable uc->dev on d1
943
944case 2
945 uc->dev d1 (a1) B1
946 new_uc->dev d11 (a1) B1
947
948 resolution: need to switch uc since d1 and d11 are related
949 (e.g. speaker and voice-speaker)
950 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
951
952case 3
953 uc->dev d1 (a1) B1
954 new_uc->dev d2 (a2) B2
955
956 resolution: no need to switch uc
957
958case 4
959 uc->dev d1 (a1) B1
960 new_uc->dev d2 (a2) B1
961
962 resolution: disable enable uc-dev on d2 since backends match
963 we cannot enable two streams on two different devices if they
964 share the same backend. e.g. if offload is on speaker device using
965 QUAD_MI2S backend and a low-latency stream is started on voice-handset
966 using the same backend, offload must also be switched to voice-handset.
967
968case 5
969 uc->dev d1 (a1) B1
970 new_uc->dev d1 (a1), 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.
975
976case 6
977 uc->dev d1 (a1) B1
978 new_uc->dev d2 (a1) B2
979
980 resolution: no need to switch
981
982case 7
983 uc->dev d1 (a1), d2 (a2) B1, B2
984 new_uc->dev d1 (a1) B1
985
986 resolution: no need to switch
987
988*/
989static snd_device_t derive_playback_snd_device(void * platform,
990 struct audio_usecase *uc,
991 struct audio_usecase *new_uc,
992 snd_device_t new_snd_device)
993{
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530994 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700995
996 snd_device_t d1 = uc->out_snd_device;
997 snd_device_t d2 = new_snd_device;
998
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530999 switch (uc->type) {
1000 case TRANSCODE_LOOPBACK :
1001 a1 = uc->stream.inout->out_config.devices;
1002 a2 = new_uc->stream.inout->out_config.devices;
1003 break;
1004 default :
1005 a1 = uc->stream.out->devices;
1006 a2 = new_uc->stream.out->devices;
1007 break;
1008 }
1009
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001010 // 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
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001442uint32_t adev_get_dsp_bit_width_enforce_mode()
1443{
1444 if (adev == NULL) {
1445 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1446 return 0;
1447 }
1448 return adev->dsp_bit_width_enforce_mode;
1449}
1450
1451static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1452{
1453 char value[PROPERTY_VALUE_MAX];
1454 int trial;
1455 uint32_t dsp_bit_width_enforce_mode = 0;
1456
1457 if (!mixer) {
1458 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
1459 __func__);
1460 return 0;
1461 }
1462
1463 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
1464 value, NULL) > 0) {
1465 trial = atoi(value);
1466 switch (trial) {
1467 case 16:
1468 dsp_bit_width_enforce_mode = 16;
1469 break;
1470 case 24:
1471 dsp_bit_width_enforce_mode = 24;
1472 break;
1473 case 32:
1474 dsp_bit_width_enforce_mode = 32;
1475 break;
1476 default:
1477 dsp_bit_width_enforce_mode = 0;
1478 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
1479 break;
1480 }
1481 }
1482
1483 return dsp_bit_width_enforce_mode;
1484}
1485
1486static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
1487 uint32_t enforce_mode,
1488 bool enable)
1489{
1490 struct mixer_ctl *ctl = NULL;
1491 const char *mixer_ctl_name = "ASM Bit Width";
1492 uint32_t asm_bit_width_mode = 0;
1493
1494 if (enforce_mode == 0) {
1495 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
1496 return;
1497 }
1498
1499 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
1500 if (!ctl) {
1501 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1502 __func__, mixer_ctl_name);
1503 return;
1504 }
1505
1506 if (enable)
1507 asm_bit_width_mode = enforce_mode;
1508 else
1509 asm_bit_width_mode = 0;
1510
1511 ALOGV("%s DSP bit width feature status is %d width=%d",
1512 __func__, enable, asm_bit_width_mode);
1513 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
1514 ALOGE("%s: Could not set ASM biwidth %d", __func__,
1515 asm_bit_width_mode);
1516
1517 return;
1518}
1519
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301520/*
1521 * if native DSD playback active
1522 */
1523bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1524{
1525 bool active = false;
1526 struct listnode *node = NULL;
1527 struct audio_usecase *uc = NULL;
1528 struct stream_out *curr_out = NULL;
1529
1530 list_for_each(node, &adev->usecase_list) {
1531 uc = node_to_item(node, struct audio_usecase, list);
1532 curr_out = (struct stream_out*) uc->stream.out;
1533
1534 if (curr_out && PCM_PLAYBACK == uc->type &&
1535 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1536 active = true;
1537 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301538 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301539 }
1540 }
1541 return active;
1542}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301543
1544static bool force_device_switch(struct audio_usecase *usecase)
1545{
1546 bool ret = false;
1547 bool is_it_true_mode = false;
1548
1549 if (is_offload_usecase(usecase->id) &&
1550 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001551 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1552 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1553 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301554 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1555 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1556 (!is_it_true_mode && adev->native_playback_enabled)){
1557 ret = true;
1558 ALOGD("napb: time to toggle native mode");
1559 }
1560 }
1561
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301562 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301563 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1564 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301565 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001566 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301567 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301568 ALOGD("Force a2dp device switch to update new encoder config");
1569 ret = true;
1570 }
1571
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301572 return ret;
1573}
1574
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301575bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
1576{
1577 bool ret=false;
1578 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
1579 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
1580 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
1581 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
1582 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
1583 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
1584 ret = true;
1585
1586 return ret;
1587}
1588
1589bool is_a2dp_device(snd_device_t out_snd_device)
1590{
1591 bool ret=false;
1592 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
1593 ret = true;
1594
1595 return ret;
1596}
1597
1598bool is_bt_soc_on(struct audio_device *adev)
1599{
1600 struct mixer_ctl *ctl;
1601 char *mixer_ctl_name = "BT SOC status";
1602 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1603 bool bt_soc_status = true;
1604 if (!ctl) {
1605 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1606 __func__, mixer_ctl_name);
1607 /*This is to ensure we dont break targets which dont have the kernel change*/
1608 return true;
1609 }
1610 bt_soc_status = mixer_ctl_get_value(ctl, 0);
1611 ALOGD("BT SOC status: %d",bt_soc_status);
1612 return bt_soc_status;
1613}
1614
1615int out_standby_l(struct audio_stream *stream);
1616
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001617int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001619 snd_device_t out_snd_device = SND_DEVICE_NONE;
1620 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621 struct audio_usecase *usecase = NULL;
1622 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001623 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001624 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001625 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001626 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301628 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1629
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630 usecase = get_usecase_from_list(adev, uc_id);
1631 if (usecase == NULL) {
1632 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1633 return -EINVAL;
1634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001635
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001636 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001637 (usecase->type == VOIP_CALL) ||
1638 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301639 if(usecase->stream.out == NULL) {
1640 ALOGE("%s: stream.out is NULL", __func__);
1641 return -EINVAL;
1642 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001643 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001644 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001645 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646 usecase->devices = usecase->stream.out->devices;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301647 } else if (usecase->type == TRANSCODE_LOOPBACK ) {
1648 if (usecase->stream.inout == NULL) {
1649 ALOGE("%s: stream.inout is NULL", __func__);
1650 return -EINVAL;
1651 }
1652 out_snd_device = usecase->stream.inout->out_config.devices;
1653 in_snd_device = usecase->stream.inout->in_config.devices;
1654 usecase->devices = (out_snd_device | in_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001655 } else {
1656 /*
1657 * If the voice call is active, use the sound devices of voice call usecase
1658 * so that it would not result any device switch. All the usecases will
1659 * be switched to new device when select_devices() is called for voice call
1660 * usecase. This is to avoid switching devices for voice call when
1661 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001662 * choose voice call device only if the use case device is
1663 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001665 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001666 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001667 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001668 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1669 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301670 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1671 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001672 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001673 in_snd_device = vc_usecase->in_snd_device;
1674 out_snd_device = vc_usecase->out_snd_device;
1675 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001676 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08001677 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08001678 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08001679 if ((voip_usecase != NULL) &&
1680 (usecase->type == PCM_PLAYBACK) &&
1681 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08001682 out_snd_device_backend_match = platform_check_backends_match(
1683 voip_usecase->out_snd_device,
1684 platform_get_output_snd_device(
1685 adev->platform,
1686 usecase->stream.out));
1687 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001688 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001689 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1690 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08001691 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001692 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001693 in_snd_device = voip_usecase->in_snd_device;
1694 out_snd_device = voip_usecase->out_snd_device;
1695 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001696 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001697 hfp_ucid = audio_extn_hfp_get_usecase();
1698 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001699 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001700 in_snd_device = hfp_usecase->in_snd_device;
1701 out_snd_device = hfp_usecase->out_snd_device;
1702 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001703 }
1704 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301705 if (usecase->stream.out == NULL) {
1706 ALOGE("%s: stream.out is NULL", __func__);
1707 return -EINVAL;
1708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001709 usecase->devices = usecase->stream.out->devices;
1710 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001711 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001712 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001713 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001714 if (usecase->stream.out == adev->primary_output &&
1715 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001716 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001717 select_devices(adev, adev->active_input->usecase);
1718 }
1719 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001720 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301721 if (usecase->stream.in == NULL) {
1722 ALOGE("%s: stream.in is NULL", __func__);
1723 return -EINVAL;
1724 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725 usecase->devices = usecase->stream.in->device;
1726 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001727 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001728 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001729 if (adev->active_input &&
1730 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301731 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1732 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1733 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001734 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001735 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001736 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1737 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001738 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001739 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001740 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001741 }
1742 }
1743
1744 if (out_snd_device == usecase->out_snd_device &&
1745 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301746
1747 if (!force_device_switch(usecase))
1748 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 }
1750
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301751 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
1752 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready())) {
1753 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1754 return 0;
1755 }
1756
sangwoobc677242013-08-08 16:53:43 +09001757 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001758 out_snd_device, platform_get_snd_device_name(out_snd_device),
1759 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761 /*
1762 * Limitation: While in call, to do a device switch we need to disable
1763 * and enable both RX and TX devices though one of them is same as current
1764 * device.
1765 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001766 if ((usecase->type == VOICE_CALL) &&
1767 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1768 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001769 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001770 }
1771
1772 if (((usecase->type == VOICE_CALL) ||
1773 (usecase->type == VOIP_CALL)) &&
1774 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1775 /* Disable sidetone only if voice/voip call already exists */
1776 if (voice_is_call_state_active(adev) ||
1777 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001778 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001779
1780 /* Disable aanc only if voice call exists */
1781 if (voice_is_call_state_active(adev))
1782 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001783 }
1784
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 /* Disable current sound devices */
1786 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001787 disable_audio_route(adev, usecase);
1788 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 }
1790
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001791 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001792 disable_audio_route(adev, usecase);
1793 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 }
1795
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001796 /* Applicable only on the targets that has external modem.
1797 * New device information should be sent to modem before enabling
1798 * the devices to reduce in-call device switch time.
1799 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001800 if ((usecase->type == VOICE_CALL) &&
1801 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1802 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001803 status = platform_switch_voice_call_enable_device_config(adev->platform,
1804 out_snd_device,
1805 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001806 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001807
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001808 /* Enable new sound devices */
1809 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001810 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301811 if (platform_check_codec_asrc_support(adev->platform))
1812 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001813 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 }
1815
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001816 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301817 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001818 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001819 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001820
Avinash Vaish71a8b972014-07-24 15:36:33 +05301821 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001822 status = platform_switch_voice_call_device_post(adev->platform,
1823 out_snd_device,
1824 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301825 enable_audio_route_for_voice_usecases(adev, usecase);
1826 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001827
sangwoo170731f2013-06-08 15:36:36 +09001828 usecase->in_snd_device = in_snd_device;
1829 usecase->out_snd_device = out_snd_device;
1830
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301831 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1832 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301833 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001834 if ((24 == usecase->stream.out->bit_width) &&
1835 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1836 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1837 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1838 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1839 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1840 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1841 /*
1842 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1843 * configured device sample rate, if not update the COPP rate to be equal to the
1844 * device sample rate, else open COPP at stream sample rate
1845 */
1846 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1847 usecase->stream.out->sample_rate,
1848 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301849 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1850 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001851 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1852 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1853 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1854 }
1855
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001856 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001857 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001858 audio_extn_gef_notify_device_config(
1859 usecase->stream.out->devices,
1860 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001861 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001862 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001863 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301864 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001865 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001866
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001867 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001868 /* Enable aanc only if voice call exists */
1869 if (voice_is_call_state_active(adev))
1870 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1871
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001872 /* Enable sidetone only if other voice/voip call already exists */
1873 if (voice_is_call_state_active(adev) ||
1874 voice_extn_compress_voip_is_started(adev))
1875 voice_set_sidetone(adev, out_snd_device, true);
1876 }
1877
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001878 /* Applicable only on the targets that has external modem.
1879 * Enable device command should be sent to modem only after
1880 * enabling voice call mixer controls
1881 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001882 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001883 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1884 out_snd_device,
1885 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301886
1887 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
1888
1889 if (usecase->type == VOIP_CALL) {
1890 if (adev->active_input != NULL &&
1891 !adev->active_input->standby) {
1892 if (is_bt_soc_on(adev) == false){
1893 ALOGD("BT SCO MIC disconnected while in connection");
1894 if (adev->active_input->pcm != NULL)
1895 pcm_stop(adev->active_input->pcm);
1896 }
1897 }
1898 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
1899 && usecase->stream.out->started) {
1900 if (is_bt_soc_on(adev) == false) {
1901 ALOGD("BT SCO/A2DP disconnected while in connection");
1902 out_standby_l(&usecase->stream.out->stream.common);
1903 }
1904 }
1905 } else if ((usecase->stream.out != NULL) &&
1906 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
1907 usecase->stream.out->started) {
1908 if (is_bt_soc_on(adev) == false) {
1909 ALOGD("BT SCO/A2dp disconnected while in connection");
1910 out_standby_l(&usecase->stream.out->stream.common);
1911 }
1912 }
1913 }
1914
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301915 ALOGD("%s: done",__func__);
1916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917 return status;
1918}
1919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920static int stop_input_stream(struct stream_in *in)
1921{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301922 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 struct audio_usecase *uc_info;
1924 struct audio_device *adev = in->dev;
1925
Eric Laurent994a6932013-07-17 11:51:42 -07001926 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 uc_info = get_usecase_from_list(adev, in->usecase);
1929 if (uc_info == NULL) {
1930 ALOGE("%s: Could not find the usecase (%d) in the list",
1931 __func__, in->usecase);
1932 return -EINVAL;
1933 }
1934
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001935 /* Close in-call recording streams */
1936 voice_check_and_stop_incall_rec_usecase(adev, in);
1937
Eric Laurent150dbfe2013-02-27 14:31:02 -08001938 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001939 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940
1941 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001942 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001944 list_remove(&uc_info->list);
1945 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001947 adev->active_input = get_next_active_input(adev);
1948
Eric Laurent994a6932013-07-17 11:51:42 -07001949 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 return ret;
1951}
1952
1953int start_input_stream(struct stream_in *in)
1954{
1955 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001956 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957 struct audio_usecase *uc_info;
1958 struct audio_device *adev = in->dev;
1959
Mingming Yin2664a5b2015-09-03 10:53:11 -07001960 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1961 if (get_usecase_from_list(adev, usecase) == NULL)
1962 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301963 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1964 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001965
Naresh Tanniru80659832014-06-04 18:17:56 +05301966
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05301967 if (CARD_STATUS_OFFLINE == in->card_status||
1968 CARD_STATUS_OFFLINE == adev->card_status) {
1969 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301970 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301971 goto error_config;
1972 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301973
Ashish Jain1b9b30c2017-05-18 20:57:40 +05301974 if (audio_is_bluetooth_sco_device(in->device)) {
1975 if (!adev->bt_sco_on) {
1976 ALOGE("%s: SCO profile is not ready, return error", __func__);
1977 ret = -EIO;
1978 goto error_config;
1979 }
1980 }
1981
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001982 /* Check if source matches incall recording usecase criteria */
1983 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1984 if (ret)
1985 goto error_config;
1986 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001987 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1988
1989 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1990 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1991 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001992 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001993 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001994
Eric Laurentb23d5282013-05-14 15:27:20 -07001995 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 if (in->pcm_device_id < 0) {
1997 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1998 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001999 ret = -EINVAL;
2000 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002002
2003 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002005
2006 if (!uc_info) {
2007 ret = -ENOMEM;
2008 goto error_config;
2009 }
2010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 uc_info->id = in->usecase;
2012 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002013 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002014 uc_info->devices = in->device;
2015 uc_info->in_snd_device = SND_DEVICE_NONE;
2016 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002018 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302019 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2020 adev->perf_lock_opts,
2021 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002022 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302024 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
2025 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002026
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302027 if (audio_extn_cin_attached_usecase(in->usecase)) {
2028 ret = audio_extn_cin_start_input_stream(in);
2029 if (ret)
2030 goto error_open;
2031 else
2032 goto done_open;
2033 }
2034
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002035 unsigned int flags = PCM_IN;
2036 unsigned int pcm_open_retry_count = 0;
2037
2038 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2039 flags |= PCM_MMAP | PCM_NOIRQ;
2040 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002041 } else if (in->realtime) {
2042 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002043 }
2044
2045 while (1) {
2046 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
2047 flags, &in->config);
2048 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2049 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2050 if (in->pcm != NULL) {
2051 pcm_close(in->pcm);
2052 in->pcm = NULL;
2053 }
2054 if (pcm_open_retry_count-- == 0) {
2055 ret = -EIO;
2056 goto error_open;
2057 }
2058 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2059 continue;
2060 }
2061 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002063
2064 ALOGV("%s: pcm_prepare", __func__);
2065 ret = pcm_prepare(in->pcm);
2066 if (ret < 0) {
2067 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2068 pcm_close(in->pcm);
2069 in->pcm = NULL;
2070 goto error_open;
2071 }
2072
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002073 register_in_stream(in);
2074 if (in->realtime) {
2075 ret = pcm_start(in->pcm);
2076 if (ret < 0)
2077 goto error_open;
2078 }
2079
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302080done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302081 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002082 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002083
Eric Laurentc8400632013-02-14 19:04:54 -08002084 return ret;
2085
2086error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302087 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002088 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002089error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302090 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302091 /*
2092 * sleep 50ms to allow sufficient time for kernel
2093 * drivers to recover incases like SSR.
2094 */
2095 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002096 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002097
2098 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099}
2100
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002101void lock_input_stream(struct stream_in *in)
2102{
2103 pthread_mutex_lock(&in->pre_lock);
2104 pthread_mutex_lock(&in->lock);
2105 pthread_mutex_unlock(&in->pre_lock);
2106}
2107
2108void lock_output_stream(struct stream_out *out)
2109{
2110 pthread_mutex_lock(&out->pre_lock);
2111 pthread_mutex_lock(&out->lock);
2112 pthread_mutex_unlock(&out->pre_lock);
2113}
2114
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115/* must be called with out->lock locked */
2116static int send_offload_cmd_l(struct stream_out* out, int command)
2117{
2118 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2119
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002120 if (!cmd) {
2121 ALOGE("failed to allocate mem for command 0x%x", command);
2122 return -ENOMEM;
2123 }
2124
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 ALOGVV("%s %d", __func__, command);
2126
2127 cmd->cmd = command;
2128 list_add_tail(&out->offload_cmd_list, &cmd->node);
2129 pthread_cond_signal(&out->offload_cond);
2130 return 0;
2131}
2132
2133/* must be called iwth out->lock locked */
2134static void stop_compressed_output_l(struct stream_out *out)
2135{
2136 out->offload_state = OFFLOAD_STATE_IDLE;
2137 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002138 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 if (out->compr != NULL) {
2140 compress_stop(out->compr);
2141 while (out->offload_thread_blocked) {
2142 pthread_cond_wait(&out->cond, &out->lock);
2143 }
2144 }
2145}
2146
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002147bool is_offload_usecase(audio_usecase_t uc_id)
2148{
2149 unsigned int i;
2150 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2151 if (uc_id == offload_usecases[i])
2152 return true;
2153 }
2154 return false;
2155}
2156
Dhananjay Kumarac341582017-02-23 23:42:25 +05302157static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002158{
vivek mehta446c3962015-09-14 10:57:35 -07002159 audio_usecase_t ret_uc = USECASE_INVALID;
2160 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002161 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002162 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302163 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002164 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2165 else
2166 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002167
vivek mehta446c3962015-09-14 10:57:35 -07002168 pthread_mutex_lock(&adev->lock);
2169 if (get_usecase_from_list(adev, ret_uc) != NULL)
2170 ret_uc = USECASE_INVALID;
2171 pthread_mutex_unlock(&adev->lock);
2172
2173 return ret_uc;
2174 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002175
2176 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002177 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2178 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2179 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2180 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002181 break;
2182 }
2183 }
vivek mehta446c3962015-09-14 10:57:35 -07002184
2185 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2186 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002187}
2188
2189static void free_offload_usecase(struct audio_device *adev,
2190 audio_usecase_t uc_id)
2191{
vivek mehta446c3962015-09-14 10:57:35 -07002192 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002193 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002194
2195 if (!adev->multi_offload_enable)
2196 return;
2197
2198 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2199 if (offload_usecases[offload_uc_index] == uc_id) {
2200 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002201 break;
2202 }
2203 }
2204 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2205}
2206
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207static void *offload_thread_loop(void *context)
2208{
2209 struct stream_out *out = (struct stream_out *) context;
2210 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002211 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002212
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2214 set_sched_policy(0, SP_FOREGROUND);
2215 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2216
2217 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002218 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002219 for (;;) {
2220 struct offload_cmd *cmd = NULL;
2221 stream_callback_event_t event;
2222 bool send_callback = false;
2223
2224 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2225 __func__, list_empty(&out->offload_cmd_list),
2226 out->offload_state);
2227 if (list_empty(&out->offload_cmd_list)) {
2228 ALOGV("%s SLEEPING", __func__);
2229 pthread_cond_wait(&out->offload_cond, &out->lock);
2230 ALOGV("%s RUNNING", __func__);
2231 continue;
2232 }
2233
2234 item = list_head(&out->offload_cmd_list);
2235 cmd = node_to_item(item, struct offload_cmd, node);
2236 list_remove(item);
2237
2238 ALOGVV("%s STATE %d CMD %d out->compr %p",
2239 __func__, out->offload_state, cmd->cmd, out->compr);
2240
2241 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2242 free(cmd);
2243 break;
2244 }
2245
2246 if (out->compr == NULL) {
2247 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002248 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249 pthread_cond_signal(&out->cond);
2250 continue;
2251 }
2252 out->offload_thread_blocked = true;
2253 pthread_mutex_unlock(&out->lock);
2254 send_callback = false;
2255 switch(cmd->cmd) {
2256 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002257 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002258 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002259 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002260 send_callback = true;
2261 event = STREAM_CBK_EVENT_WRITE_READY;
2262 break;
2263 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002264 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302265 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002266 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302267 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002268 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302269 if (ret < 0)
2270 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302271 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302272 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002273 compress_drain(out->compr);
2274 else
2275 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302276 if (ret != -ENETRESET) {
2277 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302278 pthread_mutex_lock(&out->lock);
2279 out->send_new_metadata = 1;
2280 out->send_next_track_params = true;
2281 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302282 event = STREAM_CBK_EVENT_DRAIN_READY;
2283 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2284 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302285 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002286 break;
2287 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002288 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002289 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002290 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002291 send_callback = true;
2292 event = STREAM_CBK_EVENT_DRAIN_READY;
2293 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302294 case OFFLOAD_CMD_ERROR:
2295 ALOGD("copl(%p): sending error callback to AF", out);
2296 send_callback = true;
2297 event = STREAM_CBK_EVENT_ERROR;
2298 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002299 default:
2300 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2301 break;
2302 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002303 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002304 out->offload_thread_blocked = false;
2305 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002306 if (send_callback && out->client_callback) {
2307 ALOGVV("%s: sending client_callback event %d", __func__, event);
2308 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002309 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002310 free(cmd);
2311 }
2312
2313 pthread_cond_signal(&out->cond);
2314 while (!list_empty(&out->offload_cmd_list)) {
2315 item = list_head(&out->offload_cmd_list);
2316 list_remove(item);
2317 free(node_to_item(item, struct offload_cmd, node));
2318 }
2319 pthread_mutex_unlock(&out->lock);
2320
2321 return NULL;
2322}
2323
2324static int create_offload_callback_thread(struct stream_out *out)
2325{
2326 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2327 list_init(&out->offload_cmd_list);
2328 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2329 offload_thread_loop, out);
2330 return 0;
2331}
2332
2333static int destroy_offload_callback_thread(struct stream_out *out)
2334{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002335 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002336 stop_compressed_output_l(out);
2337 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2338
2339 pthread_mutex_unlock(&out->lock);
2340 pthread_join(out->offload_thread, (void **) NULL);
2341 pthread_cond_destroy(&out->offload_cond);
2342
2343 return 0;
2344}
2345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346static int stop_output_stream(struct stream_out *out)
2347{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302348 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349 struct audio_usecase *uc_info;
2350 struct audio_device *adev = out->dev;
2351
Eric Laurent994a6932013-07-17 11:51:42 -07002352 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002353 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 uc_info = get_usecase_from_list(adev, out->usecase);
2355 if (uc_info == NULL) {
2356 ALOGE("%s: Could not find the usecase (%d) in the list",
2357 __func__, out->usecase);
2358 return -EINVAL;
2359 }
2360
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002361 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302362 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002363 if (adev->visualizer_stop_output != NULL)
2364 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002365
2366 audio_extn_dts_remove_state_notifier_node(out->usecase);
2367
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002368 if (adev->offload_effects_stop_output != NULL)
2369 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2370 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002371
Eric Laurent150dbfe2013-02-27 14:31:02 -08002372 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002373 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002374
2375 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002376 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002378 if (is_offload_usecase(out->usecase)) {
2379 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2380 adev->dsp_bit_width_enforce_mode,
2381 false);
2382 }
2383
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002384 list_remove(&uc_info->list);
2385 free(uc_info);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302386 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002387 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302388 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002389 ALOGV("Disable passthrough , reset mixer to pcm");
2390 /* NO_PASSTHROUGH */
2391 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002392 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002393 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2394 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002395
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302396 /* Must be called after removing the usecase from list */
2397 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302398 audio_extn_keep_alive_start();
2399
Naresh Tanniru85819452017-05-04 18:55:45 -07002400 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
2401 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
2402 if (ret < 0)
2403 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
2404 }
2405
Eric Laurent994a6932013-07-17 11:51:42 -07002406 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407 return ret;
2408}
2409
2410int start_output_stream(struct stream_out *out)
2411{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413 struct audio_usecase *uc_info;
2414 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002415 char mixer_ctl_name[128];
2416 struct mixer_ctl *ctl = NULL;
2417 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002419 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2420 ret = -EINVAL;
2421 goto error_config;
2422 }
2423
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302424 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2425 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2426 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302427
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302428 if (CARD_STATUS_OFFLINE == out->card_status ||
2429 CARD_STATUS_OFFLINE == adev->card_status) {
2430 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302431 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302432 goto error_config;
2433 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302434
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302435 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2436 if (!audio_extn_a2dp_is_ready()) {
2437 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2438 //combo usecase just by pass a2dp
2439 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2440 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2441 } else {
2442 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2443 ret = -EAGAIN;
2444 goto error_config;
2445 }
2446 }
2447 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302448 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2449 if (!adev->bt_sco_on) {
2450 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2451 //combo usecase just by pass a2dp
2452 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
2453 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2454 } else {
2455 ALOGE("%s: SCO profile is not ready, return error", __func__);
2456 ret = -EAGAIN;
2457 goto error_config;
2458 }
2459 }
2460 }
2461
Eric Laurentb23d5282013-05-14 15:27:20 -07002462 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463 if (out->pcm_device_id < 0) {
2464 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2465 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002466 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002467 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 }
2469
2470 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002471
2472 if (!uc_info) {
2473 ret = -ENOMEM;
2474 goto error_config;
2475 }
2476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477 uc_info->id = out->usecase;
2478 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002479 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002480 uc_info->devices = out->devices;
2481 uc_info->in_snd_device = SND_DEVICE_NONE;
2482 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002483 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302485 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2486 adev->perf_lock_opts,
2487 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302488
2489 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2490 audio_extn_keep_alive_stop();
2491 if (audio_extn_passthru_is_enabled() &&
2492 audio_extn_passthru_is_passthrough_stream(out)) {
2493 audio_extn_passthru_on_start(out);
2494 audio_extn_passthru_update_stream_configuration(adev, out);
2495 }
2496 }
2497
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002498 select_devices(adev, out->usecase);
2499
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002500 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2501 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002502 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002503 unsigned int flags = PCM_OUT;
2504 unsigned int pcm_open_retry_count = 0;
2505 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2506 flags |= PCM_MMAP | PCM_NOIRQ;
2507 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002508 } else if (out->realtime) {
2509 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002510 } else
2511 flags |= PCM_MONOTONIC;
2512
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002513 if ((adev->vr_audio_mode_enabled) &&
2514 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2515 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2516 "PCM_Dev %d Topology", out->pcm_device_id);
2517 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2518 if (!ctl) {
2519 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2520 __func__, mixer_ctl_name);
2521 } else {
2522 //if success use ULLPP
2523 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2524 __func__, mixer_ctl_name, out->pcm_device_id);
2525 //There is a still a possibility that some sessions
2526 // that request for FAST|RAW when 3D audio is active
2527 //can go through ULLPP. Ideally we expects apps to
2528 //listen to audio focus and stop concurrent playback
2529 //Also, we will look for mode flag (voice_in_communication)
2530 //before enabling the realtime flag.
2531 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2532 }
2533 }
2534
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002535 while (1) {
2536 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2537 flags, &out->config);
2538 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2539 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2540 if (out->pcm != NULL) {
2541 pcm_close(out->pcm);
2542 out->pcm = NULL;
2543 }
2544 if (pcm_open_retry_count-- == 0) {
2545 ret = -EIO;
2546 goto error_open;
2547 }
2548 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2549 continue;
2550 }
2551 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002552 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002553
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002554 ALOGV("%s: pcm_prepare", __func__);
2555 if (pcm_is_ready(out->pcm)) {
2556 ret = pcm_prepare(out->pcm);
2557 if (ret < 0) {
2558 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2559 pcm_close(out->pcm);
2560 out->pcm = NULL;
2561 goto error_open;
2562 }
2563 }
Divya Narayanan Poojary2c429012017-04-20 16:37:20 +05302564 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302565 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
2566
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002567 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002568 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05302569 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002570 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
2571 adev->dsp_bit_width_enforce_mode,
2572 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002574 out->compr = compress_open(adev->snd_card,
2575 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 COMPRESS_IN, &out->compr_config);
2577 if (out->compr && !is_compress_ready(out->compr)) {
2578 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2579 compress_close(out->compr);
2580 out->compr = NULL;
2581 ret = -EIO;
2582 goto error_open;
2583 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302584 /* compress_open sends params of the track, so reset the flag here */
2585 out->is_compr_metadata_avail = false;
2586
Ben Rombergerd771a7c2017-02-22 18:05:17 -08002587 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002588 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002589
Fred Oh3f43e742015-03-04 18:42:34 -08002590 /* Since small bufs uses blocking writes, a write will be blocked
2591 for the default max poll time (20s) in the event of an SSR.
2592 Reduce the poll time to observe and deal with SSR faster.
2593 */
Ashish Jain5106d362016-05-11 19:23:33 +05302594 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002595 compress_set_max_poll_wait(out->compr, 1000);
2596 }
2597
Manish Dewangan69426c82017-01-30 17:35:36 +05302598 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05302599 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05302600
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002601 audio_extn_dts_create_state_notifier_node(out->usecase);
2602 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2603 popcount(out->channel_mask),
2604 out->playback_started);
2605
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002606#ifdef DS1_DOLBY_DDP_ENABLED
2607 if (audio_extn_is_dolby_format(out->format))
2608 audio_extn_dolby_send_ddp_endp_params(adev);
2609#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302610 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2611 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002612 if (adev->visualizer_start_output != NULL)
2613 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2614 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302615 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002616 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002619
2620 if (ret == 0) {
2621 register_out_stream(out);
2622 if (out->realtime) {
2623 ret = pcm_start(out->pcm);
2624 if (ret < 0)
2625 goto error_open;
2626 }
2627 }
2628
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302629 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002630 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002631
Naresh Tanniru85819452017-05-04 18:55:45 -07002632 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07002633 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07002634 if (ret < 0)
2635 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
2636 }
2637
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002638 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002639error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302640 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002642error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302643 /*
2644 * sleep 50ms to allow sufficient time for kernel
2645 * drivers to recover incases like SSR.
2646 */
2647 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002648 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649}
2650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651static int check_input_parameters(uint32_t sample_rate,
2652 audio_format_t format,
2653 int channel_count)
2654{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002655 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302657 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2658 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2659 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002660 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302661 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002662
2663 switch (channel_count) {
2664 case 1:
2665 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302666 case 3:
2667 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002668 case 6:
2669 break;
2670 default:
2671 ret = -EINVAL;
2672 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673
2674 switch (sample_rate) {
2675 case 8000:
2676 case 11025:
2677 case 12000:
2678 case 16000:
2679 case 22050:
2680 case 24000:
2681 case 32000:
2682 case 44100:
2683 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302684 case 96000:
2685 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 break;
2687 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002688 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 }
2690
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002691 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692}
2693
2694static size_t get_input_buffer_size(uint32_t sample_rate,
2695 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002696 int channel_count,
2697 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698{
2699 size_t size = 0;
2700
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002701 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2702 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002704 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002705 if (is_low_latency)
2706 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302707
2708 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002710 /* make sure the size is multiple of 32 bytes
2711 * At 48 kHz mono 16-bit PCM:
2712 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2713 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2714 */
2715 size += 0x1f;
2716 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002717
2718 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719}
2720
Ashish Jain058165c2016-09-28 23:18:48 +05302721static size_t get_output_period_size(uint32_t sample_rate,
2722 audio_format_t format,
2723 int channel_count,
2724 int duration /*in millisecs*/)
2725{
2726 size_t size = 0;
2727 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2728
2729 if ((duration == 0) || (sample_rate == 0) ||
2730 (bytes_per_sample == 0) || (channel_count == 0)) {
2731 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2732 bytes_per_sample, channel_count);
2733 return -EINVAL;
2734 }
2735
2736 size = (sample_rate *
2737 duration *
2738 bytes_per_sample *
2739 channel_count) / 1000;
2740 /*
2741 * To have same PCM samples for all channels, the buffer size requires to
2742 * be multiple of (number of channels * bytes per sample)
2743 * For writes to succeed, the buffer must be written at address which is multiple of 32
2744 */
2745 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2746
2747 return (size/(channel_count * bytes_per_sample));
2748}
2749
Ashish Jain5106d362016-05-11 19:23:33 +05302750static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2751{
2752 uint64_t actual_frames_rendered = 0;
2753 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2754
2755 /* This adjustment accounts for buffering after app processor.
2756 * It is based on estimated DSP latency per use case, rather than exact.
2757 */
2758 int64_t platform_latency = platform_render_latency(out->usecase) *
2759 out->sample_rate / 1000000LL;
2760
2761 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2762 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2763 * hence only estimate.
2764 */
2765 int64_t signed_frames = out->written - kernel_buffer_size;
2766
2767 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2768
2769 if (signed_frames > 0)
2770 actual_frames_rendered = signed_frames;
2771
2772 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2773 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2774 (long long int)out->written, (int)kernel_buffer_size,
2775 audio_bytes_per_sample(out->compr_config.codec->format),
2776 popcount(out->channel_mask));
2777
2778 return actual_frames_rendered;
2779}
2780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2782{
2783 struct stream_out *out = (struct stream_out *)stream;
2784
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002785 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786}
2787
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002788static int out_set_sample_rate(struct audio_stream *stream __unused,
2789 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790{
2791 return -ENOSYS;
2792}
2793
2794static size_t out_get_buffer_size(const struct audio_stream *stream)
2795{
2796 struct stream_out *out = (struct stream_out *)stream;
2797
Naresh Tanniruee3499a2017-01-05 14:05:35 +05302798 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2799 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
2800 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
2801 else
2802 return out->compr_config.fragment_size;
2803 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002804 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05302805 else if (is_offload_usecase(out->usecase) &&
2806 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302807 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002809 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002810 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811}
2812
2813static uint32_t out_get_channels(const struct audio_stream *stream)
2814{
2815 struct stream_out *out = (struct stream_out *)stream;
2816
2817 return out->channel_mask;
2818}
2819
2820static audio_format_t out_get_format(const struct audio_stream *stream)
2821{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 struct stream_out *out = (struct stream_out *)stream;
2823
2824 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825}
2826
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002827static int out_set_format(struct audio_stream *stream __unused,
2828 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829{
2830 return -ENOSYS;
2831}
2832
2833static int out_standby(struct audio_stream *stream)
2834{
2835 struct stream_out *out = (struct stream_out *)stream;
2836 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302838 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2839 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002841 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002843 if (adev->adm_deregister_stream)
2844 adev->adm_deregister_stream(adev->adm_data, out->handle);
2845
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002846 if (is_offload_usecase(out->usecase))
2847 stop_compressed_output_l(out);
2848
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002849 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002851 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2852 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302853 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08002854 pthread_mutex_unlock(&adev->lock);
2855 pthread_mutex_unlock(&out->lock);
2856 ALOGD("VOIP output entered standby");
2857 return 0;
2858 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 if (out->pcm) {
2860 pcm_close(out->pcm);
2861 out->pcm = NULL;
2862 }
2863 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002864 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302865 out->send_next_track_params = false;
2866 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002867 out->gapless_mdata.encoder_delay = 0;
2868 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002869 if (out->compr != NULL) {
2870 compress_close(out->compr);
2871 out->compr = NULL;
2872 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002873 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002875 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 }
2877 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302878 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 return 0;
2880}
2881
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302882static int out_on_error(struct audio_stream *stream)
2883{
2884 struct stream_out *out = (struct stream_out *)stream;
2885 bool do_standby = false;
2886
2887 lock_output_stream(out);
2888 if (!out->standby) {
2889 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2890 stop_compressed_output_l(out);
2891 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2892 } else
2893 do_standby = true;
2894 }
2895 pthread_mutex_unlock(&out->lock);
2896
2897 if (do_standby)
2898 return out_standby(&out->stream.common);
2899
2900 return 0;
2901}
2902
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302903/*
2904 *standby implementation without locks, assumes that the callee already
2905 *has taken adev and out lock.
2906 */
2907int out_standby_l(struct audio_stream *stream)
2908{
2909 struct stream_out *out = (struct stream_out *)stream;
2910 struct audio_device *adev = out->dev;
2911
2912 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2913 stream, out->usecase, use_case_table[out->usecase]);
2914
2915 if (!out->standby) {
2916 if (adev->adm_deregister_stream)
2917 adev->adm_deregister_stream(adev->adm_data, out->handle);
2918
2919 if (is_offload_usecase(out->usecase))
2920 stop_compressed_output_l(out);
2921
2922 out->standby = true;
2923 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2924 voice_extn_compress_voip_close_output_stream(stream);
2925 out->started = 0;
2926 ALOGD("VOIP output entered standby");
2927 return 0;
2928 } else if (!is_offload_usecase(out->usecase)) {
2929 if (out->pcm) {
2930 pcm_close(out->pcm);
2931 out->pcm = NULL;
2932 }
2933 } else {
2934 ALOGD("copl(%p):standby", out);
2935 out->send_next_track_params = false;
2936 out->is_compr_metadata_avail = false;
2937 out->gapless_mdata.encoder_delay = 0;
2938 out->gapless_mdata.encoder_padding = 0;
2939 if (out->compr != NULL) {
2940 compress_close(out->compr);
2941 out->compr = NULL;
2942 }
2943 }
2944 stop_output_stream(out);
2945 }
2946 ALOGD("%s: exit", __func__);
2947 return 0;
2948}
2949
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002950static int out_dump(const struct audio_stream *stream __unused,
2951 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952{
2953 return 0;
2954}
2955
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002956static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2957{
2958 int ret = 0;
2959 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002960
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002961 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002962 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002963 return -EINVAL;
2964 }
2965
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302966 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002967
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002968 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2969 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302970 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002971 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002972 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2973 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302974 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002975 }
2976
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002977 ALOGV("%s new encoder delay %u and padding %u", __func__,
2978 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2979
2980 return 0;
2981}
2982
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002983static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2984{
2985 return out == adev->primary_output || out == adev->voice_tx_output;
2986}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002987
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302988// note: this call is safe only if the stream_cb is
2989// removed first in close_output_stream (as is done now).
2990static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2991{
2992 if (!stream || !parms)
2993 return;
2994
2995 struct stream_out *out = (struct stream_out *)stream;
2996 struct audio_device *adev = out->dev;
2997
2998 card_status_t status;
2999 int card;
3000 if (parse_snd_card_status(parms, &card, &status) < 0)
3001 return;
3002
3003 pthread_mutex_lock(&adev->lock);
3004 bool valid_cb = (card == adev->snd_card);
3005 pthread_mutex_unlock(&adev->lock);
3006
3007 if (!valid_cb)
3008 return;
3009
3010 lock_output_stream(out);
3011 if (out->card_status != status)
3012 out->card_status = status;
3013 pthread_mutex_unlock(&out->lock);
3014
3015 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
3016 use_case_table[out->usecase],
3017 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3018
3019 if (status == CARD_STATUS_OFFLINE)
3020 out_on_error(stream);
3021
3022 return;
3023}
3024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
3026{
3027 struct stream_out *out = (struct stream_out *)stream;
3028 struct audio_device *adev = out->dev;
3029 struct str_parms *parms;
3030 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003031 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032
sangwoobc677242013-08-08 16:53:43 +09003033 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003034 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303036 if (!parms)
3037 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003038 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3039 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003041 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003042 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003044 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003045 * When HDMI cable is unplugged the music playback is paused and
3046 * the policy manager sends routing=0. But the audioflinger continues
3047 * to write data until standby time (3sec). As the HDMI core is
3048 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003049 * Avoid this by routing audio to speaker until standby.
3050 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003051 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
3052 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303053 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08003054 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
3055 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003056 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303057 /*
3058 * When A2DP is disconnected the
3059 * music playback is paused and the policy manager sends routing=0
3060 * But the audioflingercontinues to write data until standby time
3061 * (3sec). As BT is turned off, the write gets blocked.
3062 * Avoid this by routing audio to speaker until standby.
3063 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07003064 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05303065 (val == AUDIO_DEVICE_NONE)) {
3066 val = AUDIO_DEVICE_OUT_SPEAKER;
3067 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303068 /* To avoid a2dp to sco overlapping / BT device improper state
3069 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303070 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303071 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3072 if (!audio_extn_a2dp_is_ready()) {
3073 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
3074 //combo usecase just by pass a2dp
3075 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
3076 val = AUDIO_DEVICE_OUT_SPEAKER;
3077 } else {
3078 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3079 /* update device to a2dp and don't route as BT returned error
3080 * However it is still possible a2dp routing called because
3081 * of current active device disconnection (like wired headset)
3082 */
3083 out->devices = val;
3084 pthread_mutex_unlock(&out->lock);
3085 pthread_mutex_unlock(&adev->lock);
3086 goto error;
3087 }
3088 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05303089 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003090 /*
3091 * select_devices() call below switches all the usecases on the same
3092 * backend to the new device. Refer to check_usecases_codec_backend() in
3093 * the select_devices(). But how do we undo this?
3094 *
3095 * For example, music playback is active on headset (deep-buffer usecase)
3096 * and if we go to ringtones and select a ringtone, low-latency usecase
3097 * will be started on headset+speaker. As we can't enable headset+speaker
3098 * and headset devices at the same time, select_devices() switches the music
3099 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3100 * So when the ringtone playback is completed, how do we undo the same?
3101 *
3102 * We are relying on the out_set_parameters() call on deep-buffer output,
3103 * once the ringtone playback is ended.
3104 * NOTE: We should not check if the current devices are same as new devices.
3105 * Because select_devices() must be called to switch back the music
3106 * playback to headset.
3107 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003108 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003109 audio_devices_t new_dev = val;
3110 bool same_dev = out->devices == new_dev;
3111 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003112
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003113 if (output_drives_call(adev, out)) {
3114 if(!voice_is_in_call(adev)) {
3115 if (adev->mode == AUDIO_MODE_IN_CALL) {
3116 adev->current_call_output = out;
3117 ret = voice_start_call(adev);
3118 }
3119 } else {
3120 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003121 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07003122 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003123 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003124
3125 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003126 if (!same_dev) {
3127 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05303128 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3129 adev->perf_lock_opts,
3130 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07003131 if (adev->adm_on_routing_change)
3132 adev->adm_on_routing_change(adev->adm_data,
3133 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003134 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003135 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05303136 if (!same_dev)
3137 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08003138 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003139 }
3140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003142 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003144
3145 if (out == adev->primary_output) {
3146 pthread_mutex_lock(&adev->lock);
3147 audio_extn_set_parameters(adev, parms);
3148 pthread_mutex_unlock(&adev->lock);
3149 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003150 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003151 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003152 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003153
3154 audio_extn_dts_create_state_notifier_node(out->usecase);
3155 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3156 popcount(out->channel_mask),
3157 out->playback_started);
3158
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08003159 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003160 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003161
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303162 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3163 if (err >= 0) {
3164 strlcpy(out->profile, value, sizeof(out->profile));
3165 ALOGV("updating stream profile with value '%s'", out->profile);
3166 lock_output_stream(out);
3167 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
3168 &adev->streams_output_cfg_list,
3169 out->devices, out->flags, out->format,
3170 out->sample_rate, out->bit_width,
3171 out->channel_mask, out->profile,
3172 &out->app_type_cfg);
3173 pthread_mutex_unlock(&out->lock);
3174 }
3175
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303177error:
Eric Laurent994a6932013-07-17 11:51:42 -07003178 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 return ret;
3180}
3181
3182static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3183{
3184 struct stream_out *out = (struct stream_out *)stream;
3185 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003186 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 char value[256];
3188 struct str_parms *reply = str_parms_create();
3189 size_t i, j;
3190 int ret;
3191 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003192
3193 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003194 if (reply) {
3195 str_parms_destroy(reply);
3196 }
3197 if (query) {
3198 str_parms_destroy(query);
3199 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003200 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
3201 return NULL;
3202 }
3203
Eric Laurent994a6932013-07-17 11:51:42 -07003204 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3206 if (ret >= 0) {
3207 value[0] = '\0';
3208 i = 0;
3209 while (out->supported_channel_masks[i] != 0) {
3210 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3211 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3212 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003213 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003215 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 first = false;
3217 break;
3218 }
3219 }
3220 i++;
3221 }
3222 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3223 str = str_parms_to_str(reply);
3224 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003225 voice_extn_out_get_parameters(out, query, reply);
3226 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003228
Alexy Joseph62142aa2015-11-16 15:10:34 -08003229
3230 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
3231 if (ret >= 0) {
3232 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05303233 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
3234 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08003235 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303236 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003237 } else {
3238 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05303239 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08003240 }
3241 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003242 if (str)
3243 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08003244 str = str_parms_to_str(reply);
3245 }
3246
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003247 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
3248 if (ret >= 0) {
3249 value[0] = '\0';
3250 i = 0;
3251 first = true;
3252 while (out->supported_formats[i] != 0) {
3253 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
3254 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
3255 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08003256 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003257 }
3258 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
3259 first = false;
3260 break;
3261 }
3262 }
3263 i++;
3264 }
3265 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003266 if (str)
3267 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003268 str = str_parms_to_str(reply);
3269 }
Mingming Yin3a941d42016-02-17 18:08:05 -08003270
3271 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
3272 if (ret >= 0) {
3273 value[0] = '\0';
3274 i = 0;
3275 first = true;
3276 while (out->supported_sample_rates[i] != 0) {
3277 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
3278 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
3279 if (!first) {
3280 strlcat(value, "|", sizeof(value));
3281 }
3282 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
3283 first = false;
3284 break;
3285 }
3286 }
3287 i++;
3288 }
3289 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
3290 if (str)
3291 free(str);
3292 str = str_parms_to_str(reply);
3293 }
3294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 str_parms_destroy(query);
3296 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003297 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 return str;
3299}
3300
3301static uint32_t out_get_latency(const struct audio_stream_out *stream)
3302{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003303 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08003305 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306
Alexy Josephaa54c872014-12-03 02:46:47 -08003307 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05303308 lock_output_stream(out);
3309 latency = audio_extn_utils_compress_get_dsp_latency(out);
3310 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003311 } else if (out->realtime) {
3312 // since the buffer won't be filled up faster than realtime,
3313 // return a smaller number
3314 if (out->config.rate)
3315 period_ms = (out->af_period_multiplier * out->config.period_size *
3316 1000) / (out->config.rate);
3317 else
3318 period_ms = 0;
3319 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08003320 } else {
3321 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003322 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08003323 }
3324
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08003325 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
3326 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3327 latency += audio_extn_a2dp_get_encoder_latency();
3328
Anish Kumar50ebcbf2014-12-09 04:01:39 +05303329 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08003330 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331}
3332
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303333static float AmpToDb(float amplification)
3334{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303335 float db = DSD_VOLUME_MIN_DB;
3336 if (amplification > 0) {
3337 db = 20 * log10(amplification);
3338 if(db < DSD_VOLUME_MIN_DB)
3339 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303340 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05303341 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303342}
3343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344static int out_set_volume(struct audio_stream_out *stream, float left,
3345 float right)
3346{
Eric Laurenta9024de2013-04-04 09:19:12 -07003347 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 int volume[2];
3349
Eric Laurenta9024de2013-04-04 09:19:12 -07003350 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3351 /* only take left channel into account: the API is for stereo anyway */
3352 out->muted = (left == 0.0f);
3353 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003354 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303355 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003356 /*
3357 * Set mute or umute on HDMI passthrough stream.
3358 * Only take left channel into account.
3359 * Mute is 0 and unmute 1
3360 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303361 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05303362 } else if (out->format == AUDIO_FORMAT_DSD){
3363 char mixer_ctl_name[128] = "DSD Volume";
3364 struct audio_device *adev = out->dev;
3365 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3366
3367 if (!ctl) {
3368 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3369 __func__, mixer_ctl_name);
3370 return -EINVAL;
3371 }
3372 volume[0] = (int)(AmpToDb(left));
3373 volume[1] = (int)(AmpToDb(right));
3374 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3375 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003376 } else {
3377 char mixer_ctl_name[128];
3378 struct audio_device *adev = out->dev;
3379 struct mixer_ctl *ctl;
3380 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003381 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003383 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3384 "Compress Playback %d Volume", pcm_device_id);
3385 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3386 if (!ctl) {
3387 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3388 __func__, mixer_ctl_name);
3389 return -EINVAL;
3390 }
3391 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3392 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3393 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3394 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003395 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003396 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 return -ENOSYS;
3399}
3400
3401static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3402 size_t bytes)
3403{
3404 struct stream_out *out = (struct stream_out *)stream;
3405 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003406 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003408 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303409
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303410 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003411
Dhananjay Kumarac341582017-02-23 23:42:25 +05303412 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303413 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303414 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3415 pthread_mutex_unlock(&out->lock);
3416 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303417 } else {
3418 /* increase written size during SSR to avoid mismatch
3419 * with the written frames count in AF
3420 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003421 // bytes per frame
3422 size_t bpf = audio_bytes_per_sample(out->format) *
3423 audio_channel_count_from_out_mask(out->channel_mask);
3424 if (bpf != 0)
3425 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303426 ALOGD(" %s: sound card is not active/SSR state", __func__);
3427 ret= -EIO;
3428 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303429 }
3430 }
3431
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303432 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303433 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ben Romberger4863ed72017-06-23 14:25:27 -07003434 if ((audio_bytes_per_sample(out->format) != 0) && (out->config.channels != 0))
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303435 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3436 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303437 goto exit;
3438 }
3439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003440 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003441 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003442 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003443 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3444 ret = voice_extn_compress_voip_start_output_stream(out);
3445 else
3446 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003447 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003448 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003450 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451 goto exit;
3452 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303453 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003454 if (last_known_cal_step != -1) {
3455 ALOGD("%s: retry previous failed cal level set", __func__);
3456 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05303457 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07003458 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460
Ashish Jain81eb2a82015-05-13 10:52:34 +05303461 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003462 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303463 adev->is_channel_status_set = true;
3464 }
3465
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003466 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003467 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003468 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003469 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003470 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3471 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303472 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3473 ALOGD("copl(%p):send next track params in gapless", out);
3474 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3475 out->send_next_track_params = false;
3476 out->is_compr_metadata_avail = false;
3477 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003478 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05303479 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303480 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003481
Ashish Jain83a6cc22016-06-28 14:34:17 +05303482 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303483 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303484 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303485 pthread_mutex_unlock(&out->lock);
3486 return -EINVAL;
3487 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303488 audio_format_t dst_format = out->hal_op_format;
3489 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303490
3491 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3492 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3493
Ashish Jain83a6cc22016-06-28 14:34:17 +05303494 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303495 dst_format,
3496 buffer,
3497 src_format,
3498 frames);
3499
Ashish Jain83a6cc22016-06-28 14:34:17 +05303500 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303501 bytes_to_write);
3502
3503 /*Convert written bytes in audio flinger format*/
3504 if (ret > 0)
3505 ret = ((ret * format_to_bitwidth_table[out->format]) /
3506 format_to_bitwidth_table[dst_format]);
3507 }
3508 } else
3509 ret = compress_write(out->compr, buffer, bytes);
3510
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303511 if (ret < 0)
3512 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303513 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303514 /*msg to cb thread only if non blocking write is enabled*/
3515 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303516 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003517 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303518 } else if (-ENETRESET == ret) {
3519 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303520 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05303521 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303522 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003523 }
Ashish Jain5106d362016-05-11 19:23:33 +05303524 if ( ret == (ssize_t)bytes && !out->non_blocking)
3525 out->written += bytes;
3526
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303527 /* Call compr start only when non-zero bytes of data is there to be rendered */
3528 if (!out->playback_started && ret > 0) {
3529 int status = compress_start(out->compr);
3530 if (status < 0) {
3531 ret = status;
3532 ALOGE("%s: compr start failed with err %d", __func__, errno);
3533 goto exit;
3534 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003535 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003536 out->playback_started = 1;
3537 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003538
3539 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3540 popcount(out->channel_mask),
3541 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003542 }
3543 pthread_mutex_unlock(&out->lock);
3544 return ret;
3545 } else {
3546 if (out->pcm) {
3547 if (out->muted)
3548 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003549
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303550 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003551
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003552 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003553
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003554 if (out->config.rate)
3555 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3556 out->config.rate;
3557
3558 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3559
3560 request_out_focus(out, ns);
3561
3562 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003563 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003564 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303565 out->convert_buffer != NULL) {
3566
3567 memcpy_by_audio_format(out->convert_buffer,
3568 out->hal_op_format,
3569 buffer,
3570 out->hal_ip_format,
3571 out->config.period_size * out->config.channels);
3572
3573 ret = pcm_write(out->pcm, out->convert_buffer,
3574 (out->config.period_size *
3575 out->config.channels *
3576 format_to_bitwidth_table[out->hal_op_format]));
3577 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05303578 /*
3579 * To avoid underrun in DSP when the application is not pumping
3580 * data at required rate, check for the no. of bytes and ignore
3581 * pcm_write if it is less than actual buffer size.
3582 * It is a work around to a change in compress VOIP driver.
3583 */
3584 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
3585 bytes < (out->config.period_size * out->config.channels *
3586 audio_bytes_per_sample(out->format))) {
3587 size_t voip_buf_size =
3588 out->config.period_size * out->config.channels *
3589 audio_bytes_per_sample(out->format);
3590 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
3591 __func__, bytes, voip_buf_size);
3592 usleep(((uint64_t)voip_buf_size - bytes) *
3593 1000000 / audio_stream_out_frame_size(stream) /
3594 out_get_sample_rate(&out->stream.common));
3595 ret = 0;
3596 } else
3597 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303598 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003599
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003600 release_out_focus(out);
3601
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303602 if (ret < 0)
3603 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303604 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3605 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3606 else
3607 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 }
3610
3611exit:
Naresh Tanniru4c630392014-05-12 01:05:52 +05303612 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303613 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 pthread_mutex_unlock(&out->lock);
3616
3617 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003618 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003619 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303620 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303621 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303622 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303623 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303624 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303625 out->standby = true;
3626 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303627 out_on_error(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303628 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3629 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3630 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 }
3632 return bytes;
3633}
3634
3635static int out_get_render_position(const struct audio_stream_out *stream,
3636 uint32_t *dsp_frames)
3637{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003638 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08003639
3640 if (dsp_frames == NULL)
3641 return -EINVAL;
3642
3643 *dsp_frames = 0;
3644 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003645 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303646
3647 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3648 * this operation and adev_close_output_stream(where out gets reset).
3649 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05303650 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303651 *dsp_frames = get_actual_pcm_frames_rendered(out);
3652 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3653 return 0;
3654 }
3655
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003656 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303657 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303658 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003659 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303660 if (ret < 0)
3661 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303663 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303665 if (-ENETRESET == ret) {
3666 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303667 out->card_status = CARD_STATUS_OFFLINE;
3668 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303669 } else if(ret < 0) {
3670 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303671 ret = -EINVAL;
3672 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303673 /*
3674 * Handle corner case where compress session is closed during SSR
3675 * and timestamp is queried
3676 */
3677 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303678 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303679 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303680 ret = 0;
Naresh Tanniru80659832014-06-04 18:17:56 +05303681 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303682 pthread_mutex_unlock(&out->lock);
3683 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08003684 } else if (audio_is_linear_pcm(out->format)) {
3685 *dsp_frames = out->written;
3686 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003687 } else
3688 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689}
3690
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003691static int out_add_audio_effect(const struct audio_stream *stream __unused,
3692 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693{
3694 return 0;
3695}
3696
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003697static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3698 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699{
3700 return 0;
3701}
3702
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003703static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3704 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05303706 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707}
3708
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003709static int out_get_presentation_position(const struct audio_stream_out *stream,
3710 uint64_t *frames, struct timespec *timestamp)
3711{
3712 struct stream_out *out = (struct stream_out *)stream;
3713 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003714 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003715
Ashish Jain5106d362016-05-11 19:23:33 +05303716 /* below piece of code is not guarded against any lock because audioFliner serializes
3717 * this operation and adev_close_output_stream( where out gets reset).
3718 */
3719 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05303720 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05303721 *frames = get_actual_pcm_frames_rendered(out);
3722 /* this is the best we can do */
3723 clock_gettime(CLOCK_MONOTONIC, timestamp);
3724 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3725 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3726 return 0;
3727 }
3728
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003729 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003730
Ashish Jain5106d362016-05-11 19:23:33 +05303731 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3732 ret = compress_get_tstamp(out->compr, &dsp_frames,
3733 &out->sample_rate);
3734 ALOGVV("%s rendered frames %ld sample_rate %d",
3735 __func__, dsp_frames, out->sample_rate);
3736 *frames = dsp_frames;
3737 if (ret < 0)
3738 ret = -errno;
3739 if (-ENETRESET == ret) {
3740 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303741 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05303742 ret = -EINVAL;
3743 } else
3744 ret = 0;
3745 /* this is the best we can do */
3746 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003747 } else {
3748 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003749 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003750 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3751 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003752 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003753 // This adjustment accounts for buffering after app processor.
3754 // It is based on estimated DSP latency per use case, rather than exact.
3755 signed_frames -=
3756 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3757
Eric Laurent949a0892013-09-20 09:20:13 -07003758 // It would be unusual for this value to be negative, but check just in case ...
3759 if (signed_frames >= 0) {
3760 *frames = signed_frames;
3761 ret = 0;
3762 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003763 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303764 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303765 *frames = out->written;
3766 clock_gettime(CLOCK_MONOTONIC, timestamp);
3767 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003768 }
3769 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003770 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003771 return ret;
3772}
3773
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003774static int out_set_callback(struct audio_stream_out *stream,
3775 stream_callback_t callback, void *cookie)
3776{
3777 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003778 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003779
3780 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003781 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003782 out->client_callback = callback;
3783 out->client_cookie = cookie;
3784 if (out->adsp_hdlr_stream_handle) {
3785 ret = audio_extn_adsp_hdlr_stream_set_callback(
3786 out->adsp_hdlr_stream_handle,
3787 callback,
3788 cookie);
3789 if (ret)
3790 ALOGW("%s:adsp hdlr callback registration failed %d",
3791 __func__, ret);
3792 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003793 pthread_mutex_unlock(&out->lock);
3794 return 0;
3795}
3796
3797static int out_pause(struct audio_stream_out* stream)
3798{
3799 struct stream_out *out = (struct stream_out *)stream;
3800 int status = -ENOSYS;
3801 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003802 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003803 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003804 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003805 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303806 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05303807 status = compress_pause(out->compr);
3808
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003809 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003810
Mingming Yin21854652016-04-13 11:54:02 -07003811 if (audio_extn_passthru_is_active()) {
3812 ALOGV("offload use case, pause passthru");
3813 audio_extn_passthru_on_pause(out);
3814 }
3815
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303816 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003817 audio_extn_dts_notify_playback_state(out->usecase, 0,
3818 out->sample_rate, popcount(out->channel_mask),
3819 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003820 }
3821 pthread_mutex_unlock(&out->lock);
3822 }
3823 return status;
3824}
3825
3826static int out_resume(struct audio_stream_out* stream)
3827{
3828 struct stream_out *out = (struct stream_out *)stream;
3829 int status = -ENOSYS;
3830 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003831 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003832 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003833 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003834 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003835 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303836 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303837 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003838 }
3839 if (!status) {
3840 out->offload_state = OFFLOAD_STATE_PLAYING;
3841 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303842 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003843 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3844 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003845 }
3846 pthread_mutex_unlock(&out->lock);
3847 }
3848 return status;
3849}
3850
3851static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3852{
3853 struct stream_out *out = (struct stream_out *)stream;
3854 int status = -ENOSYS;
3855 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003856 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003857 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003858 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3859 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3860 else
3861 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3862 pthread_mutex_unlock(&out->lock);
3863 }
3864 return status;
3865}
3866
3867static int out_flush(struct audio_stream_out* stream)
3868{
3869 struct stream_out *out = (struct stream_out *)stream;
3870 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003871 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003872 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003873 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003874 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3875 stop_compressed_output_l(out);
3876 out->written = 0;
3877 } else {
3878 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3879 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003880 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003881 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003882 return 0;
3883 }
3884 return -ENOSYS;
3885}
3886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887/** audio_stream_in implementation **/
3888static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3889{
3890 struct stream_in *in = (struct stream_in *)stream;
3891
3892 return in->config.rate;
3893}
3894
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003895static int in_set_sample_rate(struct audio_stream *stream __unused,
3896 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897{
3898 return -ENOSYS;
3899}
3900
3901static size_t in_get_buffer_size(const struct audio_stream *stream)
3902{
3903 struct stream_in *in = (struct stream_in *)stream;
3904
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003905 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3906 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003907 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3908 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303909 else if(audio_extn_cin_attached_usecase(in->usecase))
3910 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003911
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003912 return in->config.period_size * in->af_period_multiplier *
3913 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914}
3915
3916static uint32_t in_get_channels(const struct audio_stream *stream)
3917{
3918 struct stream_in *in = (struct stream_in *)stream;
3919
3920 return in->channel_mask;
3921}
3922
3923static audio_format_t in_get_format(const struct audio_stream *stream)
3924{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003925 struct stream_in *in = (struct stream_in *)stream;
3926
3927 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928}
3929
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003930static int in_set_format(struct audio_stream *stream __unused,
3931 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932{
3933 return -ENOSYS;
3934}
3935
3936static int in_standby(struct audio_stream *stream)
3937{
3938 struct stream_in *in = (struct stream_in *)stream;
3939 struct audio_device *adev = in->dev;
3940 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303941 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3942 stream, in->usecase, use_case_table[in->usecase]);
3943
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003944 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003945 if (!in->standby && in->is_st_session) {
3946 ALOGD("%s: sound trigger pcm stop lab", __func__);
3947 audio_extn_sound_trigger_stop_lab(in);
3948 in->standby = 1;
3949 }
3950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003952 if (adev->adm_deregister_stream)
3953 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3954
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003955 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003957 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3958 voice_extn_compress_voip_close_input_stream(stream);
3959 ALOGD("VOIP input entered standby");
3960 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303961 if (audio_extn_cin_attached_usecase(in->usecase))
3962 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003963 if (in->pcm) {
3964 pcm_close(in->pcm);
3965 in->pcm = NULL;
3966 }
3967 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003968 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003969 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970 }
3971 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003972 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973 return status;
3974}
3975
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003976static int in_dump(const struct audio_stream *stream __unused,
3977 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978{
3979 return 0;
3980}
3981
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303982static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3983{
3984 if (!stream || !parms)
3985 return;
3986
3987 struct stream_in *in = (struct stream_in *)stream;
3988 struct audio_device *adev = in->dev;
3989
3990 card_status_t status;
3991 int card;
3992 if (parse_snd_card_status(parms, &card, &status) < 0)
3993 return;
3994
3995 pthread_mutex_lock(&adev->lock);
3996 bool valid_cb = (card == adev->snd_card);
3997 pthread_mutex_unlock(&adev->lock);
3998
3999 if (!valid_cb)
4000 return;
4001
4002 lock_input_stream(in);
4003 if (in->card_status != status)
4004 in->card_status = status;
4005 pthread_mutex_unlock(&in->lock);
4006
4007 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4008 use_case_table[in->usecase],
4009 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4010
4011 // a better solution would be to report error back to AF and let
4012 // it put the stream to standby
4013 if (status == CARD_STATUS_OFFLINE)
4014 in_standby(&in->stream.common);
4015
4016 return;
4017}
4018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004019static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4020{
4021 struct stream_in *in = (struct stream_in *)stream;
4022 struct audio_device *adev = in->dev;
4023 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004025 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304027 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004028 parms = str_parms_create_str(kvpairs);
4029
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304030 if (!parms)
4031 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004032 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004033 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004034
4035 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4036 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037 val = atoi(value);
4038 /* no audio source uses val == 0 */
4039 if ((in->source != val) && (val != 0)) {
4040 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004041 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4042 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
4043 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004044 (in->config.rate == 8000 || in->config.rate == 16000 ||
4045 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004046 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004047 err = voice_extn_compress_voip_open_input_stream(in);
4048 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004049 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08004050 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004051 }
4052 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 }
4054 }
4055
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004056 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4057 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004059 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 in->device = val;
4061 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004062 if (!in->standby && !in->is_st_session) {
4063 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07004064 if (adev->adm_on_routing_change)
4065 adev->adm_on_routing_change(adev->adm_data,
4066 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004067 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004068 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 }
4070 }
4071
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304072 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4073 if (err >= 0) {
4074 strlcpy(in->profile, value, sizeof(in->profile));
4075 ALOGV("updating stream profile with value '%s'", in->profile);
4076 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4077 &adev->streams_input_cfg_list,
4078 in->device, in->flags, in->format,
4079 in->sample_rate, in->bit_width,
4080 in->profile, &in->app_type_cfg);
4081 }
4082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004084 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004085
4086 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304087error:
Eric Laurent994a6932013-07-17 11:51:42 -07004088 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 return ret;
4090}
4091
4092static char* in_get_parameters(const struct audio_stream *stream,
4093 const char *keys)
4094{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004095 struct stream_in *in = (struct stream_in *)stream;
4096 struct str_parms *query = str_parms_create_str(keys);
4097 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004098 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004099
4100 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004101 if (reply) {
4102 str_parms_destroy(reply);
4103 }
4104 if (query) {
4105 str_parms_destroy(query);
4106 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004107 ALOGE("in_get_parameters: failed to create query or reply");
4108 return NULL;
4109 }
4110
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004111 ALOGV("%s: enter: keys - %s", __func__, keys);
4112
4113 voice_extn_in_get_parameters(in, query, reply);
4114
4115 str = str_parms_to_str(reply);
4116 str_parms_destroy(query);
4117 str_parms_destroy(reply);
4118
4119 ALOGV("%s: exit: returns - %s", __func__, str);
4120 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121}
4122
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004123static int in_set_gain(struct audio_stream_in *stream __unused,
4124 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125{
4126 return 0;
4127}
4128
4129static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4130 size_t bytes)
4131{
4132 struct stream_in *in = (struct stream_in *)stream;
4133 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304134 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304135 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004137 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304138
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004139 if (in->is_st_session) {
4140 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
4141 /* Read from sound trigger HAL */
4142 audio_extn_sound_trigger_read(in, buffer, bytes);
4143 pthread_mutex_unlock(&in->lock);
4144 return bytes;
4145 }
4146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004148 pthread_mutex_lock(&adev->lock);
4149 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
4150 ret = voice_extn_compress_voip_start_input_stream(in);
4151 else
4152 ret = start_input_stream(in);
4153 pthread_mutex_unlock(&adev->lock);
4154 if (ret != 0) {
4155 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 }
4157 in->standby = 0;
4158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004160 // what's the duration requested by the client?
4161 long ns = 0;
4162
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304163 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004164 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4165 in->config.rate;
4166
4167 request_in_focus(in, ns);
4168 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004169
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304170 if (audio_extn_cin_attached_usecase(in->usecase)) {
4171 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
4172 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304173 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004174 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304175 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07004176 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004177 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004178 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304179 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004180 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304181 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4182 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4183 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
4184 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304185 ret = -EINVAL;
4186 goto exit;
4187 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304188 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304189 ret = -errno;
4190 }
4191 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304192 /* bytes read is always set to bytes for non compress usecases */
4193 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 }
4195
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004196 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198 /*
4199 * Instead of writing zeroes here, we could trust the hardware
4200 * to always provide zeroes when muted.
4201 */
Pavan Chikkala63964842014-12-04 10:48:28 +05304202 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
4203 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204 memset(buffer, 0, bytes);
4205
4206exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004207 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304208 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 pthread_mutex_unlock(&in->lock);
4210
4211 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304212 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304213 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304214 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304215 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05304216 in->standby = true;
4217 }
Sharad Sangled17c9122017-03-20 15:58:52 +05304218 if (!audio_extn_cin_attached_usecase(in->usecase)) {
4219 bytes_read = bytes;
4220 memset(buffer, 0, bytes);
4221 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004223 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05304224 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05304225 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304227 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228}
4229
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004230static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231{
4232 return 0;
4233}
4234
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004235static int add_remove_audio_effect(const struct audio_stream *stream,
4236 effect_handle_t effect,
4237 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004239 struct stream_in *in = (struct stream_in *)stream;
4240 int status = 0;
4241 effect_descriptor_t desc;
4242
4243 status = (*effect)->get_descriptor(effect, &desc);
4244 if (status != 0)
4245 return status;
4246
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004247 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004248 pthread_mutex_lock(&in->dev->lock);
4249 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
4250 in->enable_aec != enable &&
4251 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4252 in->enable_aec = enable;
4253 if (!in->standby)
4254 select_devices(in->dev, in->usecase);
4255 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08004256 if (in->enable_ns != enable &&
4257 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4258 in->enable_ns = enable;
4259 if (!in->standby)
4260 select_devices(in->dev, in->usecase);
4261 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004262 pthread_mutex_unlock(&in->dev->lock);
4263 pthread_mutex_unlock(&in->lock);
4264
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004265 return 0;
4266}
4267
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004268static int in_add_audio_effect(const struct audio_stream *stream,
4269 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270{
Eric Laurent994a6932013-07-17 11:51:42 -07004271 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004272 return add_remove_audio_effect(stream, effect, true);
4273}
4274
4275static int in_remove_audio_effect(const struct audio_stream *stream,
4276 effect_handle_t effect)
4277{
Eric Laurent994a6932013-07-17 11:51:42 -07004278 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004279 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280}
4281
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304282int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004283 audio_io_handle_t handle,
4284 audio_devices_t devices,
4285 audio_output_flags_t flags,
4286 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004287 struct audio_stream_out **stream_out,
4288 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004289{
4290 struct audio_device *adev = (struct audio_device *)dev;
4291 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304292 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004293 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004294 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05304297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4299
Mingming Yin3a941d42016-02-17 18:08:05 -08004300 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
4301 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304302 devices, flags, &out->stream);
4303
4304
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004305 if (!out) {
4306 return -ENOMEM;
4307 }
4308
Haynes Mathew George204045b2015-02-25 20:32:03 -08004309 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004310 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08004311 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 if (devices == AUDIO_DEVICE_NONE)
4314 devices = AUDIO_DEVICE_OUT_SPEAKER;
4315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 out->flags = flags;
4317 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004318 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004319 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004320 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05304321 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004322 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07004323 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004324 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08004325 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304326 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304327 out->started = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004328
Mingming Yin3a941d42016-02-17 18:08:05 -08004329 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4330 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
4331 pthread_mutex_lock(&adev->lock);
4332 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
4333 ret = read_hdmi_sink_caps(out);
4334 pthread_mutex_unlock(&adev->lock);
4335 if (ret != 0) {
4336 if (ret == -ENOSYS) {
4337 /* ignore and go with default */
4338 ret = 0;
4339 } else {
4340 ALOGE("error reading hdmi sink caps");
4341 goto error_open;
4342 }
4343 }
4344 }
4345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346 /* Init use case and pcm_config */
Dhananjay Kumarac341582017-02-23 23:42:25 +05304347 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004348 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08004349 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004350 ret = voice_extn_compress_voip_open_output_stream(out);
4351 if (ret != 0) {
4352 ALOGE("%s: Compress voip output cannot be opened, error:%d",
4353 __func__, ret);
4354 goto error_open;
4355 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004356 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304357 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304358 pthread_mutex_lock(&adev->lock);
4359 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4360 pthread_mutex_unlock(&adev->lock);
4361
4362 // reject offload during card offline to allow
4363 // fallback to s/w paths
4364 if (offline) {
4365 ret = -ENODEV;
4366 goto error_open;
4367 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004368
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004369 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4370 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4371 ALOGE("%s: Unsupported Offload information", __func__);
4372 ret = -EINVAL;
4373 goto error_open;
4374 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004375
Mingming Yin3a941d42016-02-17 18:08:05 -08004376 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004377 if(config->offload_info.format == 0)
4378 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08004379 if (config->offload_info.sample_rate == 0)
4380 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004381 }
4382
Mingming Yin90310102013-11-13 16:57:00 -08004383 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304384 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07004385 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004386 ret = -EINVAL;
4387 goto error_open;
4388 }
4389
Ben Romberger0f8c87b2017-05-24 17:41:11 -07004390 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
4391 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
4392 (audio_extn_passthru_is_passthrough_stream(out)) &&
4393 !((config->sample_rate == 48000) ||
4394 (config->sample_rate == 96000) ||
4395 (config->sample_rate == 192000))) {
4396 ALOGE("%s: Unsupported sample rate %d for audio format %x",
4397 __func__, config->sample_rate, config->offload_info.format);
4398 ret = -EINVAL;
4399 goto error_open;
4400 }
4401
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004402 out->compr_config.codec = (struct snd_codec *)
4403 calloc(1, sizeof(struct snd_codec));
4404
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004405 if (!out->compr_config.codec) {
4406 ret = -ENOMEM;
4407 goto error_open;
4408 }
4409
Dhananjay Kumarac341582017-02-23 23:42:25 +05304410 out->stream.pause = out_pause;
4411 out->stream.resume = out_resume;
4412 out->stream.flush = out_flush;
4413 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07004414 out->stream.set_callback = out_set_callback;
Mingming Yin21d60472015-09-30 13:56:25 -07004415 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05304416 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07004417 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304418 } else {
4419 out->usecase = get_offload_usecase(adev, false /* is_compress */);
4420 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004421 }
vivek mehta446c3962015-09-14 10:57:35 -07004422
4423 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004424 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4425 config->format == 0 && config->sample_rate == 0 &&
4426 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004427 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004428 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4429 } else {
4430 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4431 ret = -EEXIST;
4432 goto error_open;
4433 }
vivek mehta446c3962015-09-14 10:57:35 -07004434 }
4435
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004436 if (config->offload_info.channel_mask)
4437 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004438 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004439 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004440 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004441 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05304442 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004443 ret = -EINVAL;
4444 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004445 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004446
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004447 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004448 out->sample_rate = config->offload_info.sample_rate;
4449
Mingming Yin3ee55c62014-08-04 14:23:35 -07004450 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004451
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304452 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4453 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4454 audio_extn_dolby_send_ddp_endp_params(adev);
4455 audio_extn_dolby_set_dmid(adev);
4456 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004457
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004458 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004459 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004460 out->compr_config.codec->bit_rate =
4461 config->offload_info.bit_rate;
4462 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304463 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004464 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304465 /* Update bit width only for non passthrough usecases.
4466 * For passthrough usecases, the output will always be opened @16 bit
4467 */
4468 if (!audio_extn_passthru_is_passthrough_stream(out))
4469 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304470
4471 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4472 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
4473 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
4474
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004475 /*TODO: Do we need to change it for passthrough */
4476 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004477
Manish Dewangana6fc5442015-08-24 20:30:31 +05304478 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4479 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304480 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304481 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304482 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4483 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304484
4485 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4486 AUDIO_FORMAT_PCM) {
4487
4488 /*Based on platform support, configure appropriate alsa format for corresponding
4489 *hal input format.
4490 */
4491 out->compr_config.codec->format = hal_format_to_alsa(
4492 config->offload_info.format);
4493
Ashish Jain83a6cc22016-06-28 14:34:17 +05304494 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304495 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304496 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304497
Dhananjay Kumarac341582017-02-23 23:42:25 +05304498 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05304499 *hal input format and alsa format might differ based on platform support.
4500 */
4501 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304502 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304503
4504 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4505
4506 /* Check if alsa session is configured with the same format as HAL input format,
4507 * if not then derive correct fragment size needed to accomodate the
4508 * conversion of HAL input format to alsa format.
4509 */
4510 audio_extn_utils_update_direct_pcm_fragment_size(out);
4511
4512 /*if hal input and output fragment size is different this indicates HAL input format is
4513 *not same as the alsa format
4514 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304515 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304516 /*Allocate a buffer to convert input data to the alsa configured format.
4517 *size of convert buffer is equal to the size required to hold one fragment size
4518 *worth of pcm data, this is because flinger does not write more than fragment_size
4519 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304520 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4521 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304522 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4523 ret = -ENOMEM;
4524 goto error_open;
4525 }
4526 }
4527 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4528 out->compr_config.fragment_size =
4529 audio_extn_passthru_get_buffer_size(&config->offload_info);
4530 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4531 } else {
4532 out->compr_config.fragment_size =
4533 platform_get_compress_offload_buffer_size(&config->offload_info);
4534 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4535 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004536
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304537 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4538 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
4539 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07004540 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304541 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004542
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304543 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4544 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4545 }
4546
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004547 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4548 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004549
Manish Dewangan69426c82017-01-30 17:35:36 +05304550 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4551 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4552 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4553 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4554 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4555 } else {
4556 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4557 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004558
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05304559 memset(&out->channel_map_param, 0,
4560 sizeof(struct audio_out_channel_map_param));
4561
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004562 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304563 out->send_next_track_params = false;
4564 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004565 out->offload_state = OFFLOAD_STATE_IDLE;
4566 out->playback_started = 0;
4567
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004568 audio_extn_dts_create_state_notifier_node(out->usecase);
4569
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004570 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4571 __func__, config->offload_info.version,
4572 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304573
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304574 /* Check if DSD audio format is supported in codec
4575 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304576 */
4577
4578 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304579 (!platform_check_codec_dsd_support(adev->platform) ||
4580 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304581 ret = -EINVAL;
4582 goto error_open;
4583 }
4584
Ashish Jain5106d362016-05-11 19:23:33 +05304585 /* Disable gapless if any of the following is true
4586 * passthrough playback
4587 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05304588 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05304589 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304590 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304591 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07004592 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304593 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05304594 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05304595 check_and_set_gapless_mode(adev, false);
4596 } else
4597 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004598
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304599 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004600 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4601 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304602 if (config->format == AUDIO_FORMAT_DSD) {
4603 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4604 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4605 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004606
4607 create_offload_callback_thread(out);
4608
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004609 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304610 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004611 if (ret != 0) {
4612 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4613 __func__, ret);
4614 goto error_open;
4615 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004616 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4617 if (config->sample_rate == 0)
4618 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4619 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4620 config->sample_rate != 8000) {
4621 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4622 ret = -EINVAL;
4623 goto error_open;
4624 }
4625 out->sample_rate = config->sample_rate;
4626 out->config.rate = config->sample_rate;
4627 if (config->format == AUDIO_FORMAT_DEFAULT)
4628 config->format = AUDIO_FORMAT_PCM_16_BIT;
4629 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4630 config->format = AUDIO_FORMAT_PCM_16_BIT;
4631 ret = -EINVAL;
4632 goto error_open;
4633 }
4634 out->format = config->format;
4635 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4636 out->config = pcm_config_afe_proxy_playback;
4637 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004638 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304639 unsigned int channels = 0;
4640 /*Update config params to default if not set by the caller*/
4641 if (config->sample_rate == 0)
4642 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4643 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4644 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4645 if (config->format == AUDIO_FORMAT_DEFAULT)
4646 config->format = AUDIO_FORMAT_PCM_16_BIT;
4647
4648 channels = audio_channel_count_from_out_mask(out->channel_mask);
4649
Ashish Jain83a6cc22016-06-28 14:34:17 +05304650 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4651 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004652 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4653 out->flags);
4654 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304655 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4656 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4657 out->config = pcm_config_low_latency;
4658 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4659 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4660 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304661 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4662 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4663 if (out->config.period_size <= 0) {
4664 ALOGE("Invalid configuration period size is not valid");
4665 ret = -EINVAL;
4666 goto error_open;
4667 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304668 } else {
4669 /* primary path is the default path selected if no other outputs are available/suitable */
4670 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4671 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4672 }
4673 out->hal_ip_format = format = out->format;
4674 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4675 out->hal_op_format = pcm_format_to_hal(out->config.format);
4676 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4677 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004678 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304679 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304680 if (out->hal_ip_format != out->hal_op_format) {
4681 uint32_t buffer_size = out->config.period_size *
4682 format_to_bitwidth_table[out->hal_op_format] *
4683 out->config.channels;
4684 out->convert_buffer = calloc(1, buffer_size);
4685 if (out->convert_buffer == NULL){
4686 ALOGE("Allocation failed for convert buffer for size %d",
4687 out->compr_config.fragment_size);
4688 ret = -ENOMEM;
4689 goto error_open;
4690 }
4691 ALOGD("Convert buffer allocated of size %d", buffer_size);
4692 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 }
4694
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004695 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4696 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304697
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004698 /* TODO remove this hardcoding and check why width is zero*/
4699 if (out->bit_width == 0)
4700 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304701 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004702 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304703 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304704 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304705 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004706 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4707 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4708 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004709 if(adev->primary_output == NULL)
4710 adev->primary_output = out;
4711 else {
4712 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004713 ret = -EEXIST;
4714 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004715 }
4716 }
4717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718 /* Check if this usecase is already existing */
4719 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004720 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4721 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004724 ret = -EEXIST;
4725 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728 pthread_mutex_unlock(&adev->lock);
4729
4730 out->stream.common.get_sample_rate = out_get_sample_rate;
4731 out->stream.common.set_sample_rate = out_set_sample_rate;
4732 out->stream.common.get_buffer_size = out_get_buffer_size;
4733 out->stream.common.get_channels = out_get_channels;
4734 out->stream.common.get_format = out_get_format;
4735 out->stream.common.set_format = out_set_format;
4736 out->stream.common.standby = out_standby;
4737 out->stream.common.dump = out_dump;
4738 out->stream.common.set_parameters = out_set_parameters;
4739 out->stream.common.get_parameters = out_get_parameters;
4740 out->stream.common.add_audio_effect = out_add_audio_effect;
4741 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4742 out->stream.get_latency = out_get_latency;
4743 out->stream.set_volume = out_set_volume;
4744 out->stream.write = out_write;
4745 out->stream.get_render_position = out_get_render_position;
4746 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004747 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004749 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004751 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004752 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004753
4754 config->format = out->stream.common.get_format(&out->stream.common);
4755 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4756 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4757
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304758 /*
4759 By locking output stream before registering, we allow the callback
4760 to update stream's state only after stream's initial state is set to
4761 adev state.
4762 */
4763 lock_output_stream(out);
4764 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4765 pthread_mutex_lock(&adev->lock);
4766 out->card_status = adev->card_status;
4767 pthread_mutex_unlock(&adev->lock);
4768 pthread_mutex_unlock(&out->lock);
4769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304771 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004772 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004773
4774 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4775 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4776 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004777 /* setup a channel for client <--> adsp communication for stream events */
4778 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07004779 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
4780 (audio_extn_ip_hdlr_intf_supported(config->format))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004781 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
4782 out->usecase, PCM_PLAYBACK);
4783 hdlr_stream_cfg.flags = out->flags;
4784 hdlr_stream_cfg.type = PCM_PLAYBACK;
4785 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
4786 &hdlr_stream_cfg);
4787 if (ret) {
4788 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
4789 out->adsp_hdlr_stream_handle = NULL;
4790 }
4791 }
Naresh Tanniru85819452017-05-04 18:55:45 -07004792 if (audio_extn_ip_hdlr_intf_supported(config->format)) {
4793 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL);
4794 if (ret < 0) {
4795 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
4796 out->ip_hdlr_handle = NULL;
4797 }
4798 }
Eric Laurent994a6932013-07-17 11:51:42 -07004799 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004801
4802error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304803 if (out->convert_buffer)
4804 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004805 free(out);
4806 *stream_out = NULL;
4807 ALOGD("%s: exit: ret %d", __func__, ret);
4808 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004809}
4810
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304811void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812 struct audio_stream_out *stream)
4813{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004814 struct stream_out *out = (struct stream_out *)stream;
4815 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004816 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004817
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304818 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4819
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304820 // must deregister from sndmonitor first to prevent races
4821 // between the callback and close_stream
4822 audio_extn_snd_mon_unregister_listener(out);
4823
Ben Rombergerd771a7c2017-02-22 18:05:17 -08004824 /* close adsp hdrl session before standby */
4825 if (out->adsp_hdlr_stream_handle) {
4826 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
4827 if (ret)
4828 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
4829 out->adsp_hdlr_stream_handle = NULL;
4830 }
4831
Naresh Tanniru85819452017-05-04 18:55:45 -07004832 if (audio_extn_ip_hdlr_intf_supported(out->format) && out->ip_hdlr_handle) {
4833 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
4834 out->ip_hdlr_handle = NULL;
4835 }
4836
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004837 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304838 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004839 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304840 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304841 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004842 if(ret != 0)
4843 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4844 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004845 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004846 out_standby(&stream->common);
4847
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004848 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004849 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004850 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004851 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004852 if (out->compr_config.codec != NULL)
4853 free(out->compr_config.codec);
4854 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004855
Ashish Jain83a6cc22016-06-28 14:34:17 +05304856 if (out->convert_buffer != NULL) {
4857 free(out->convert_buffer);
4858 out->convert_buffer = NULL;
4859 }
4860
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004861 if (adev->voice_tx_output == out)
4862 adev->voice_tx_output = NULL;
4863
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304864 if (adev->primary_output == out)
4865 adev->primary_output = NULL;
4866
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004867 pthread_cond_destroy(&out->cond);
4868 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004870 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004871}
4872
4873static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4874{
4875 struct audio_device *adev = (struct audio_device *)dev;
4876 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004878 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004879 int ret;
4880 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004881
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004882 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304885 if (!parms)
4886 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304887
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304888 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
4889 if (ret >= 0) {
4890 /* When set to false, HAL should disable EC and NS */
4891 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4892 adev->bt_sco_on = true;
4893 else
4894 adev->bt_sco_on = false;
4895 }
4896
Naresh Tanniru4c630392014-05-12 01:05:52 +05304897 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004898 status = voice_set_parameters(adev, parms);
4899 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004900 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004902 status = platform_set_parameters(adev->platform, parms);
4903 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004904 goto done;
4905
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004906 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4907 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004908 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004909 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4910 adev->bluetooth_nrec = true;
4911 else
4912 adev->bluetooth_nrec = false;
4913 }
4914
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004915 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4916 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4918 adev->screen_off = false;
4919 else
4920 adev->screen_off = true;
4921 }
4922
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004923 ret = str_parms_get_int(parms, "rotation", &val);
4924 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004925 bool reverse_speakers = false;
4926 switch(val) {
4927 // FIXME: note that the code below assumes that the speakers are in the correct placement
4928 // relative to the user when the device is rotated 90deg from its default rotation. This
4929 // assumption is device-specific, not platform-specific like this code.
4930 case 270:
4931 reverse_speakers = true;
4932 break;
4933 case 0:
4934 case 90:
4935 case 180:
4936 break;
4937 default:
4938 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004939 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004940 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004941 if (status == 0) {
4942 if (adev->speaker_lr_swap != reverse_speakers) {
4943 adev->speaker_lr_swap = reverse_speakers;
4944 // only update the selected device if there is active pcm playback
4945 struct audio_usecase *usecase;
4946 struct listnode *node;
4947 list_for_each(node, &adev->usecase_list) {
4948 usecase = node_to_item(node, struct audio_usecase, list);
4949 if (usecase->type == PCM_PLAYBACK) {
4950 select_devices(adev, usecase->id);
4951 break;
4952 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004953 }
4954 }
4955 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004956 }
4957
Mingming Yin514a8bc2014-07-29 15:22:21 -07004958 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4959 if (ret >= 0) {
4960 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4961 adev->bt_wb_speech_enabled = true;
4962 else
4963 adev->bt_wb_speech_enabled = false;
4964 }
4965
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004966 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4967 if (ret >= 0) {
4968 val = atoi(value);
4969 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004970 ALOGV("cache new ext disp type and edid");
4971 ret = platform_get_ext_disp_type(adev->platform);
4972 if (ret < 0) {
4973 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004974 status = ret;
4975 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004976 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004977 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004978 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004979 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004980 /*
4981 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4982 * Per AudioPolicyManager, USB device is higher priority than WFD.
4983 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4984 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4985 * starting voice call on USB
4986 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004987 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4988 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004989 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4990 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004991 }
vivek mehta344576a2016-04-12 18:56:03 -07004992 ALOGV("detected USB connect .. disable proxy");
4993 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004994 }
4995 }
4996
4997 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4998 if (ret >= 0) {
4999 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07005000 /*
5001 * The HDMI / Displayport disconnect handling has been moved to
5002 * audio extension to ensure that its parameters are not
5003 * invalidated prior to updating sysfs of the disconnect event
5004 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
5005 */
5006 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08005007 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005008 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5009 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05305010 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
5011 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08005012 }
vivek mehta344576a2016-04-12 18:56:03 -07005013 ALOGV("detected USB disconnect .. enable proxy");
5014 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07005015 }
5016 }
5017
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305018 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
5019 if (ret >= 0) {
5020 struct audio_usecase *usecase;
5021 struct listnode *node;
5022 list_for_each(node, &adev->usecase_list) {
5023 usecase = node_to_item(node, struct audio_usecase, list);
5024 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07005025 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305026 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08005027
5028 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305029 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08005030 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305031 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305032 //force device switch to re configure encoder
5033 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305034 audio_extn_a2dp_set_handoff_mode(false);
5035 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05305036 break;
5037 }
5038 }
5039 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005040
5041 //handle vr audio setparam
5042 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5043 value, sizeof(value));
5044 if (ret >= 0) {
5045 ALOGI("Setting vr mode to be %s", value);
5046 if (!strncmp(value, "true", 4)) {
5047 adev->vr_audio_mode_enabled = true;
5048 ALOGI("Setting vr mode to true");
5049 } else if (!strncmp(value, "false", 5)) {
5050 adev->vr_audio_mode_enabled = false;
5051 ALOGI("Setting vr mode to false");
5052 } else {
5053 ALOGI("wrong vr mode set");
5054 }
5055 }
5056
Naresh Tannirucd2353e2016-08-19 00:37:25 +05305057 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08005058done:
5059 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005060 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05305061error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005062 ALOGV("%s: exit with code(%d)", __func__, status);
5063 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064}
5065
5066static char* adev_get_parameters(const struct audio_hw_device *dev,
5067 const char *keys)
5068{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005069 struct audio_device *adev = (struct audio_device *)dev;
5070 struct str_parms *reply = str_parms_create();
5071 struct str_parms *query = str_parms_create_str(keys);
5072 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05305073 char value[256] = {0};
5074 int ret = 0;
5075
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005076 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005077 if (reply) {
5078 str_parms_destroy(reply);
5079 }
5080 if (query) {
5081 str_parms_destroy(query);
5082 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005083 ALOGE("adev_get_parameters: failed to create query or reply");
5084 return NULL;
5085 }
5086
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005087 //handle vr audio getparam
5088
5089 ret = str_parms_get_str(query,
5090 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5091 value, sizeof(value));
5092
5093 if (ret >= 0) {
5094 bool vr_audio_enabled = false;
5095 pthread_mutex_lock(&adev->lock);
5096 vr_audio_enabled = adev->vr_audio_mode_enabled;
5097 pthread_mutex_unlock(&adev->lock);
5098
5099 ALOGI("getting vr mode to %d", vr_audio_enabled);
5100
5101 if (vr_audio_enabled) {
5102 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5103 "true");
5104 goto exit;
5105 } else {
5106 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
5107 "false");
5108 goto exit;
5109 }
5110 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005111
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005112 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005113 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08005114 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005115 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05305116 pthread_mutex_unlock(&adev->lock);
5117
Naresh Tannirud7205b62014-06-20 02:54:48 +05305118exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005119 str = str_parms_to_str(reply);
5120 str_parms_destroy(query);
5121 str_parms_destroy(reply);
5122
5123 ALOGV("%s: exit: returns - %s", __func__, str);
5124 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005125}
5126
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005127static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005128{
5129 return 0;
5130}
5131
5132static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5133{
Haynes Mathew George5191a852013-09-11 14:19:36 -07005134 int ret;
5135 struct audio_device *adev = (struct audio_device *)dev;
5136 pthread_mutex_lock(&adev->lock);
5137 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07005138 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005139 pthread_mutex_unlock(&adev->lock);
5140 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141}
5142
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005143static int adev_set_master_volume(struct audio_hw_device *dev __unused,
5144 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005145{
5146 return -ENOSYS;
5147}
5148
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005149static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5150 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151{
5152 return -ENOSYS;
5153}
5154
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005155static int adev_set_master_mute(struct audio_hw_device *dev __unused,
5156 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005157{
5158 return -ENOSYS;
5159}
5160
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005161static int adev_get_master_mute(struct audio_hw_device *dev __unused,
5162 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005163{
5164 return -ENOSYS;
5165}
5166
5167static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5168{
5169 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005171 pthread_mutex_lock(&adev->lock);
5172 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005173 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005174 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08005175 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005176 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07005177 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005178 adev->current_call_output = NULL;
5179 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005180 }
5181 pthread_mutex_unlock(&adev->lock);
5182 return 0;
5183}
5184
5185static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5186{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005187 int ret;
5188
5189 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08005190 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08005191 ret = voice_set_mic_mute((struct audio_device *)dev, state);
5192 pthread_mutex_unlock(&adev->lock);
5193
5194 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005195}
5196
5197static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5198{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005199 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200 return 0;
5201}
5202
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005203static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005204 const struct audio_config *config)
5205{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005206 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005208 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
5209 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005210}
5211
5212static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07005213 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005214 audio_devices_t devices,
5215 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005216 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305217 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005218 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005219 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220{
5221 struct audio_device *adev = (struct audio_device *)dev;
5222 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005223 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07005224 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005225 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305226 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305229 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
5230 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05305232 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005233
5234 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005235
5236 if (!in) {
5237 ALOGE("failed to allocate input stream");
5238 return -ENOMEM;
5239 }
5240
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305241 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305242 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
5243 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005244 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005245 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005247 in->stream.common.get_sample_rate = in_get_sample_rate;
5248 in->stream.common.set_sample_rate = in_set_sample_rate;
5249 in->stream.common.get_buffer_size = in_get_buffer_size;
5250 in->stream.common.get_channels = in_get_channels;
5251 in->stream.common.get_format = in_get_format;
5252 in->stream.common.set_format = in_set_format;
5253 in->stream.common.standby = in_standby;
5254 in->stream.common.dump = in_dump;
5255 in->stream.common.set_parameters = in_set_parameters;
5256 in->stream.common.get_parameters = in_get_parameters;
5257 in->stream.common.add_audio_effect = in_add_audio_effect;
5258 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5259 in->stream.set_gain = in_set_gain;
5260 in->stream.read = in_read;
5261 in->stream.get_input_frames_lost = in_get_input_frames_lost;
5262
5263 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005264 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005265 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005266 in->standby = 1;
5267 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005268 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005269 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270
Dhananjay Kumar973fc362017-01-09 18:48:15 +05305271 in->usecase = USECASE_AUDIO_RECORD;
5272 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
5273 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
5274 is_low_latency = true;
5275#if LOW_LATENCY_CAPTURE_USE_CASE
5276 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
5277#endif
5278 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
5279 }
5280
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005281 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005282 if (in->realtime) {
5283 in->config = pcm_config_audio_capture_rt;
5284 in->sample_rate = in->config.rate;
5285 in->af_period_multiplier = af_period_multiplier;
5286 } else {
5287 in->config = pcm_config_audio_capture;
5288 in->config.rate = config->sample_rate;
5289 in->sample_rate = config->sample_rate;
5290 in->af_period_multiplier = 1;
5291 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305292 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005293
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305294 /* restrict 24 bit capture for unprocessed source only
5295 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
5296 */
5297 if (config->format == AUDIO_FORMAT_DEFAULT) {
5298 config->format = AUDIO_FORMAT_PCM_16_BIT;
5299 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
5300 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
5301 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
5302 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
5303 bool ret_error = false;
5304 in->bit_width = 24;
5305 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5306 from HAL is 24_packed and 8_24
5307 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5308 24_packed return error indicating supported format is 24_packed
5309 *> In case of any other source requesting 24 bit or float return error
5310 indicating format supported is 16 bit only.
5311
5312 on error flinger will retry with supported format passed
5313 */
5314 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
5315 (source != AUDIO_SOURCE_CAMCORDER)) {
5316 config->format = AUDIO_FORMAT_PCM_16_BIT;
5317 if (config->sample_rate > 48000)
5318 config->sample_rate = 48000;
5319 ret_error = true;
5320 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
5321 in->config.format = PCM_FORMAT_S24_3LE;
5322 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5323 in->config.format = PCM_FORMAT_S24_LE;
5324 } else {
5325 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
5326 ret_error = true;
5327 }
5328
5329 if (ret_error) {
5330 ret = -EINVAL;
5331 goto err_open;
5332 }
5333 }
5334
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305335 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05305336 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
5337 (adev->mode != AUDIO_MODE_IN_CALL)) {
5338 ret = -EINVAL;
5339 goto err_open;
5340 }
5341
5342 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
5343 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07005344 if (config->sample_rate == 0)
5345 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5346 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5347 config->sample_rate != 8000) {
5348 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5349 ret = -EINVAL;
5350 goto err_open;
5351 }
5352 if (config->format == AUDIO_FORMAT_DEFAULT)
5353 config->format = AUDIO_FORMAT_PCM_16_BIT;
5354 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5355 config->format = AUDIO_FORMAT_PCM_16_BIT;
5356 ret = -EINVAL;
5357 goto err_open;
5358 }
5359
5360 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5361 in->config = pcm_config_afe_proxy_record;
5362 in->config.channels = channel_count;
5363 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05305364 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05305365 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
5366 in, config, &channel_mask_updated)) {
5367 if (channel_mask_updated == true) {
5368 ALOGD("%s: return error to retry with updated channel mask (%#x)",
5369 __func__, config->channel_mask);
5370 ret = -EINVAL;
5371 goto err_open;
5372 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05305373 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07005374 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08005375 audio_extn_compr_cap_format_supported(config->format) &&
5376 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005377 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305378 } else if (audio_extn_cin_applicable_stream(in)) {
5379 ret = audio_extn_cin_configure_input_stream(in);
5380 if (ret)
5381 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005382 } else {
5383 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005384 if (!in->realtime) {
5385 in->format = config->format;
5386 frame_size = audio_stream_in_frame_size(&in->stream);
5387 buffer_size = get_input_buffer_size(config->sample_rate,
5388 config->format,
5389 channel_count,
5390 is_low_latency);
5391 in->config.period_size = buffer_size / frame_size;
5392 }
5393
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005394 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08005395 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005396 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08005397 (in->config.rate == 8000 || in->config.rate == 16000 ||
5398 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07005399 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
5400 voice_extn_compress_voip_open_input_stream(in);
5401 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005403
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305404 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
5405 &adev->streams_input_cfg_list,
5406 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05305407 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305408
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005409 /* This stream could be for sound trigger lab,
5410 get sound trigger pcm if present */
5411 audio_extn_sound_trigger_check_and_get_session(in);
5412
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305413 lock_input_stream(in);
5414 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5415 pthread_mutex_lock(&adev->lock);
5416 in->card_status = adev->card_status;
5417 pthread_mutex_unlock(&adev->lock);
5418 pthread_mutex_unlock(&in->lock);
5419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005421 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08005422 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005423
5424err_open:
5425 free(in);
5426 *stream_in = NULL;
5427 return ret;
5428}
5429
5430static void adev_close_input_stream(struct audio_hw_device *dev,
5431 struct audio_stream_in *stream)
5432{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005433 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005434 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005435 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305436
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305437 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005438
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305439 // must deregister from sndmonitor first to prevent races
5440 // between the callback and close_stream
5441 audio_extn_snd_mon_unregister_listener(stream);
5442
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305443 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005444 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305445
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005446 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305447 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005448 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305449 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005450 if (ret != 0)
5451 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5452 __func__, ret);
5453 } else
5454 in_standby(&stream->common);
5455
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005456 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005457 audio_extn_ssr_deinit();
5458 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005459
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305460 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005461 audio_extn_compr_cap_format_supported(in->config.format))
5462 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305463
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305464 if (audio_extn_cin_attached_usecase(in->usecase))
5465 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005466
Mingming Yinfd7607b2016-01-22 12:48:44 -08005467 if (in->is_st_session) {
5468 ALOGV("%s: sound trigger pcm stop lab", __func__);
5469 audio_extn_sound_trigger_stop_lab(in);
5470 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005471 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005472 return;
5473}
5474
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305475int adev_create_audio_patch(struct audio_hw_device *dev,
5476 unsigned int num_sources,
5477 const struct audio_port_config *sources,
5478 unsigned int num_sinks,
5479 const struct audio_port_config *sinks,
5480 audio_patch_handle_t *handle)
5481{
5482
5483
5484 return audio_extn_hw_loopback_create_audio_patch(dev,
5485 num_sources,
5486 sources,
5487 num_sinks,
5488 sinks,
5489 handle);
5490
5491}
5492
5493int adev_release_audio_patch(struct audio_hw_device *dev,
5494 audio_patch_handle_t handle)
5495{
5496 return audio_extn_hw_loopback_release_audio_patch(dev, handle);
5497}
5498
5499int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
5500{
5501 return audio_extn_hw_loopback_get_audio_port(dev, config);
5502}
5503
5504int adev_set_audio_port_config(struct audio_hw_device *dev,
5505 const struct audio_port_config *config)
5506{
5507 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
5508}
5509
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005510static int adev_dump(const audio_hw_device_t *device __unused,
5511 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005512{
5513 return 0;
5514}
5515
5516static int adev_close(hw_device_t *device)
5517{
5518 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005519
5520 if (!adev)
5521 return 0;
5522
5523 pthread_mutex_lock(&adev_init_lock);
5524
5525 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305526 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005527 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005528 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305529 audio_extn_utils_release_streams_cfg_lists(
5530 &adev->streams_output_cfg_list,
5531 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305532 if (audio_extn_qaf_is_enabled())
5533 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005534 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005535 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005536 free(adev->snd_dev_ref_cnt);
5537 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005538 if (adev->adm_deinit)
5539 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305540 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005541 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305542 audio_extn_snd_mon_deinit();
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305543 audio_extn_loopback_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07005544 free(device);
5545 adev = NULL;
5546 }
5547 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005549 return 0;
5550}
5551
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005552/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5553 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5554 * just that it _might_ work.
5555 */
5556static int period_size_is_plausible_for_low_latency(int period_size)
5557{
5558 switch (period_size) {
5559 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005560 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005561 case 240:
5562 case 320:
5563 case 480:
5564 return 1;
5565 default:
5566 return 0;
5567 }
5568}
5569
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305570static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
5571{
5572 bool is_snd_card_status = false;
5573 bool is_ext_device_status = false;
5574 char value[32];
5575 int card = -1;
5576 card_status_t status;
5577
5578 if (cookie != adev || !parms)
5579 return;
5580
5581 if (!parse_snd_card_status(parms, &card, &status)) {
5582 is_snd_card_status = true;
5583 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
5584 is_ext_device_status = true;
5585 } else {
5586 // not a valid event
5587 return;
5588 }
5589
5590 pthread_mutex_lock(&adev->lock);
5591 if (card == adev->snd_card || is_ext_device_status) {
5592 if (is_snd_card_status && adev->card_status != status) {
5593 adev->card_status = status;
5594 platform_snd_card_update(adev->platform, status);
5595 audio_extn_fm_set_parameters(adev, parms);
5596 } else if (is_ext_device_status) {
5597 platform_set_parameters(adev->platform, parms);
5598 }
5599 }
5600 pthread_mutex_unlock(&adev->lock);
5601 return;
5602}
5603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604static int adev_open(const hw_module_t *module, const char *name,
5605 hw_device_t **device)
5606{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305607 int ret;
5608
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005609 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005610 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5611
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005612 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005613 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005614 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005615 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005616 ALOGD("%s: returning existing instance of adev", __func__);
5617 ALOGD("%s: exit", __func__);
5618 pthread_mutex_unlock(&adev_init_lock);
5619 return 0;
5620 }
5621
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005622 adev = calloc(1, sizeof(struct audio_device));
5623
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005624 if (!adev) {
5625 pthread_mutex_unlock(&adev_init_lock);
5626 return -ENOMEM;
5627 }
5628
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005629 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5630
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05305631#ifdef DYNAMIC_LOG_ENABLED
5632 register_for_dynamic_logging("hal");
5633#endif
5634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005635 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5636 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5637 adev->device.common.module = (struct hw_module_t *)module;
5638 adev->device.common.close = adev_close;
5639
5640 adev->device.init_check = adev_init_check;
5641 adev->device.set_voice_volume = adev_set_voice_volume;
5642 adev->device.set_master_volume = adev_set_master_volume;
5643 adev->device.get_master_volume = adev_get_master_volume;
5644 adev->device.set_master_mute = adev_set_master_mute;
5645 adev->device.get_master_mute = adev_get_master_mute;
5646 adev->device.set_mode = adev_set_mode;
5647 adev->device.set_mic_mute = adev_set_mic_mute;
5648 adev->device.get_mic_mute = adev_get_mic_mute;
5649 adev->device.set_parameters = adev_set_parameters;
5650 adev->device.get_parameters = adev_get_parameters;
5651 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5652 adev->device.open_output_stream = adev_open_output_stream;
5653 adev->device.close_output_stream = adev_close_output_stream;
5654 adev->device.open_input_stream = adev_open_input_stream;
5655 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305656 adev->device.create_audio_patch = adev_create_audio_patch;
5657 adev->device.release_audio_patch = adev_release_audio_patch;
5658 adev->device.get_audio_port = adev_get_audio_port;
5659 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005660 adev->device.dump = adev_dump;
5661
5662 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005663 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005664 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005665 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005666 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005668 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005669 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305670 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005671 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005672 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005673 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005674 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005675 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005676 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305677 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305678 adev->perf_lock_opts[0] = 0x101;
5679 adev->perf_lock_opts[1] = 0x20E;
5680 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08005681 adev->dsp_bit_width_enforce_mode = 0;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005683 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005684 adev->platform = platform_init(adev);
5685 if (!adev->platform) {
5686 free(adev->snd_dev_ref_cnt);
5687 free(adev);
5688 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5689 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005690 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305691 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005692 return -EINVAL;
5693 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005694
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305695 if (audio_extn_qaf_is_enabled()) {
5696 ret = audio_extn_qaf_init(adev);
5697 if (ret < 0) {
5698 free(adev);
5699 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5700 *device = NULL;
5701 pthread_mutex_unlock(&adev_init_lock);
5702 pthread_mutex_destroy(&adev->lock);
5703 return ret;
5704 }
5705
5706 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5707 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5708 }
5709
Eric Laurentc4aef752013-09-12 17:45:53 -07005710 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5711 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5712 if (adev->visualizer_lib == NULL) {
5713 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5714 } else {
5715 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5716 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005717 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005718 "visualizer_hal_start_output");
5719 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005720 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005721 "visualizer_hal_stop_output");
5722 }
5723 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305724 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005725 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005726 audio_extn_gef_init(adev);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05305727 audio_extn_loopback_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005728
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005729 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5730 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5731 if (adev->offload_effects_lib == NULL) {
5732 ALOGE("%s: DLOPEN failed for %s", __func__,
5733 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5734 } else {
5735 ALOGV("%s: DLOPEN successful for %s", __func__,
5736 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5737 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305738 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005739 "offload_effects_bundle_hal_start_output");
5740 adev->offload_effects_stop_output =
5741 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5742 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005743 adev->offload_effects_set_hpx_state =
5744 (int (*)(bool))dlsym(adev->offload_effects_lib,
5745 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305746 adev->offload_effects_get_parameters =
5747 (void (*)(struct str_parms *, struct str_parms *))
5748 dlsym(adev->offload_effects_lib,
5749 "offload_effects_bundle_get_parameters");
5750 adev->offload_effects_set_parameters =
5751 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5752 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005753 }
5754 }
5755
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005756 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5757 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5758 if (adev->adm_lib == NULL) {
5759 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5760 } else {
5761 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5762 adev->adm_init = (adm_init_t)
5763 dlsym(adev->adm_lib, "adm_init");
5764 adev->adm_deinit = (adm_deinit_t)
5765 dlsym(adev->adm_lib, "adm_deinit");
5766 adev->adm_register_input_stream = (adm_register_input_stream_t)
5767 dlsym(adev->adm_lib, "adm_register_input_stream");
5768 adev->adm_register_output_stream = (adm_register_output_stream_t)
5769 dlsym(adev->adm_lib, "adm_register_output_stream");
5770 adev->adm_deregister_stream = (adm_deregister_stream_t)
5771 dlsym(adev->adm_lib, "adm_deregister_stream");
5772 adev->adm_request_focus = (adm_request_focus_t)
5773 dlsym(adev->adm_lib, "adm_request_focus");
5774 adev->adm_abandon_focus = (adm_abandon_focus_t)
5775 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005776 adev->adm_set_config = (adm_set_config_t)
5777 dlsym(adev->adm_lib, "adm_set_config");
5778 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5779 dlsym(adev->adm_lib, "adm_request_focus_v2");
5780 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5781 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5782 adev->adm_on_routing_change = (adm_on_routing_change_t)
5783 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005784 }
5785 }
5786
Mingming Yin514a8bc2014-07-29 15:22:21 -07005787 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005788 //initialize this to false for now,
5789 //this will be set to true through set param
5790 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005791
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005792 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005793 *device = &adev->device.common;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08005794 adev->dsp_bit_width_enforce_mode =
5795 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005796
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305797 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5798 &adev->streams_output_cfg_list,
5799 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005800
Kiran Kandi910e1862013-10-29 13:29:42 -07005801 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005802
5803 char value[PROPERTY_VALUE_MAX];
5804 int trial;
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005805 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005806 trial = atoi(value);
5807 if (period_size_is_plausible_for_low_latency(trial)) {
5808 pcm_config_low_latency.period_size = trial;
5809 pcm_config_low_latency.start_threshold = trial / 4;
5810 pcm_config_low_latency.avail_min = trial / 4;
5811 configured_low_latency_capture_period_size = trial;
5812 }
5813 }
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005814 if (property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005815 trial = atoi(value);
5816 if (period_size_is_plausible_for_low_latency(trial)) {
5817 configured_low_latency_capture_period_size = trial;
5818 }
5819 }
5820
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005821 if (property_get("vendor.audio_hal.period_multiplier", value, NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005822 af_period_multiplier = atoi(value);
5823 if (af_period_multiplier < 0)
5824 af_period_multiplier = 2;
5825 else if (af_period_multiplier > 4)
5826 af_period_multiplier = 4;
5827
5828 ALOGV("new period_multiplier = %d", af_period_multiplier);
5829 }
5830
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07005831 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005832 pthread_mutex_unlock(&adev_init_lock);
5833
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005834 if (adev->adm_init)
5835 adev->adm_data = adev->adm_init();
5836
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305837 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305838 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005839 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305840
5841 audio_extn_snd_mon_init();
5842 pthread_mutex_lock(&adev->lock);
5843 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
5844 adev->card_status = CARD_STATUS_ONLINE;
5845 pthread_mutex_unlock(&adev->lock);
5846 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
5847
Eric Laurent994a6932013-07-17 11:51:42 -07005848 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849 return 0;
5850}
5851
5852static struct hw_module_methods_t hal_module_methods = {
5853 .open = adev_open,
5854};
5855
5856struct audio_module HAL_MODULE_INFO_SYM = {
5857 .common = {
5858 .tag = HARDWARE_MODULE_TAG,
5859 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5860 .hal_api_version = HARDWARE_HAL_API_VERSION,
5861 .id = AUDIO_HARDWARE_MODULE_ID,
5862 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005863 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005864 .methods = &hal_module_methods,
5865 },
5866};