blob: 261531db4b77a661ca3996fdfe375e564ed9bd04 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
jiabinad481a72018-07-23 12:03:17 -0700228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
jiabinad481a72018-07-23 12:03:17 -0700242#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700252 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
Haynes Mathew George03c40102016-01-29 17:57:48 -0800543static inline bool is_mmap_usecase(audio_usecase_t uc_id)
544{
545 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
546 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
547}
548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700549static int get_snd_codec_id(audio_format_t format)
550{
551 int id = 0;
552
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554 case AUDIO_FORMAT_MP3:
555 id = SND_AUDIOCODEC_MP3;
556 break;
557 case AUDIO_FORMAT_AAC:
558 id = SND_AUDIOCODEC_AAC;
559 break;
560 default:
561 ALOGE("%s: Unsupported audio format", __func__);
562 }
563
564 return id;
565}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800566
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800567static int audio_ssr_status(struct audio_device *adev)
568{
569 int ret = 0;
570 struct mixer_ctl *ctl;
571 const char *mixer_ctl_name = "Audio SSR Status";
572
573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
574 ret = mixer_ctl_get_value(ctl, 0);
575 ALOGD("%s: value: %d", __func__, ret);
576 return ret;
577}
578
vivek mehta4a824772017-06-08 19:05:49 -0700579static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
580{
581 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
582}
583
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800584static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
585{
586 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
587 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
592
593}
594
595static bool is_a2dp_device(snd_device_t out_snd_device)
596{
597 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_audio_route(struct audio_device *adev,
601 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
yixuanjiang509f0a72018-09-06 18:37:23 +0800603 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800605
606 if (usecase == NULL)
607 return -EINVAL;
608
609 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
610
yixuanjiang509f0a72018-09-06 18:37:23 +0800611 if (usecase->type == PCM_CAPTURE)
612 snd_device = usecase->in_snd_device;
613 else
614 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530615 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800616 audio_extn_utils_send_audio_calibration(adev, usecase);
yixuanjiang6c5e87c2018-08-13 11:50:26 +0800617 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
619 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700620 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700621 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int disable_audio_route(struct audio_device *adev,
628 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
yixuanjiang509f0a72018-09-06 18:37:23 +0800630 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800632
633 if (usecase == NULL)
634 return -EINVAL;
635
636 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800637 if (usecase->type == PCM_CAPTURE)
638 snd_device = usecase->in_snd_device;
639 else
640 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800642 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700643 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700644 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000645 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647 ALOGV("%s: exit", __func__);
648 return 0;
649}
650
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800651int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700652 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700654 int i, num_devices = 0;
655 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800656 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800657 if (snd_device < SND_DEVICE_MIN ||
658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800660 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700663 platform_send_audio_calibration(adev->platform, snd_device);
664
vivek mehtade4849c2016-03-03 17:23:38 -0800665 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700666 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700667 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669 }
670
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700671 /* due to the possibility of calibration overwrite between listen
672 and audio, notify sound trigger hal before audio calibration is sent */
673 audio_extn_sound_trigger_update_device_status(snd_device,
674 ST_EVENT_SND_DEVICE_BUSY);
675
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 if (audio_extn_spkr_prot_is_enabled())
677 audio_extn_spkr_prot_calib_cancel(adev);
678
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, true);
680
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800682 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800683 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700686 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800687 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700688 }
689 if (audio_extn_spkr_prot_start_processing(snd_device)) {
690 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800691 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700693 } else if (platform_can_split_snd_device(snd_device,
694 &num_devices,
695 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700696 for (i = 0; i < num_devices; i++) {
697 enable_snd_device(adev, new_snd_devices[i]);
698 }
vivek mehtab6506412015-08-07 16:55:17 -0700699 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
702 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
703 ALOGE(" %s: Invalid sound device returned", __func__);
704 goto on_error;
705 }
Ed Tam70b5c142016-03-21 19:14:29 -0700706
Eric Laurent2e140aa2016-06-30 17:14:46 -0700707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700708
709 if (is_a2dp_device(snd_device) &&
710 (audio_extn_a2dp_start_playback() < 0)) {
711 ALOGE("%s: failed to configure A2DP control path", __func__);
712 goto on_error;
713 }
714
vivek mehtade4849c2016-03-03 17:23:38 -0800715 audio_route_apply_and_update_path(adev->audio_route, device_name);
716 }
717on_success:
718 adev->snd_dev_ref_cnt[snd_device]++;
719 ret_val = 0;
720on_error:
721 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722}
723
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800724int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[2];
729
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800730 if (snd_device < SND_DEVICE_MIN ||
731 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800732 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 return -EINVAL;
734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700735 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
736 ALOGE("%s: device ref cnt is already 0", __func__);
737 return -EINVAL;
738 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800739 audio_extn_tfa_98xx_disable_speaker(snd_device);
740
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 adev->snd_dev_ref_cnt[snd_device]--;
742 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800743 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800744
745 if (is_a2dp_device(snd_device))
746 audio_extn_a2dp_stop_playback();
747
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700748 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800749 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700750 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700751 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
752 audio_extn_spkr_prot_is_enabled()) {
753 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700754
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700755 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
756 // and does not use speaker swap. As this code causes a problem with device enable ref
757 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700758 // when speaker device is disabled, reset swap.
759 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700760 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700761
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700762 } else if (platform_can_split_snd_device(snd_device,
763 &num_devices,
764 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700765 for (i = 0; i < num_devices; i++) {
766 disable_snd_device(adev, new_snd_devices[i]);
767 }
vivek mehtab6506412015-08-07 16:55:17 -0700768 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700769 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800770 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
771 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
772 ALOGE(" %s: Invalid sound device returned", __func__);
773 return -EINVAL;
774 }
775
Eric Laurent2e140aa2016-06-30 17:14:46 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800777 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700778 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700779 audio_extn_sound_trigger_update_device_status(snd_device,
780 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 return 0;
784}
785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786/*
787 legend:
788 uc - existing usecase
789 new_uc - new usecase
790 d1, d11, d2 - SND_DEVICE enums
791 a1, a2 - corresponding ANDROID device enums
792 B, B1, B2 - backend strings
793
794case 1
795 uc->dev d1 (a1) B1
796 new_uc->dev d1 (a1), d2 (a2) B1, B2
797
798 resolution: disable and enable uc->dev on d1
799
800case 2
801 uc->dev d1 (a1) B1
802 new_uc->dev d11 (a1) B1
803
804 resolution: need to switch uc since d1 and d11 are related
805 (e.g. speaker and voice-speaker)
806 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
807
808case 3
809 uc->dev d1 (a1) B1
810 new_uc->dev d2 (a2) B2
811
812 resolution: no need to switch uc
813
814case 4
815 uc->dev d1 (a1) B
816 new_uc->dev d2 (a2) B
817
818 resolution: disable enable uc-dev on d2 since backends match
819 we cannot enable two streams on two different devices if they
820 share the same backend. e.g. if offload is on speaker device using
821 QUAD_MI2S backend and a low-latency stream is started on voice-handset
822 using the same backend, offload must also be switched to voice-handset.
823
824case 5
825 uc->dev d1 (a1) B
826 new_uc->dev d1 (a1), d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend.
831
832case 6
833 uc->dev d1 a1 B1
834 new_uc->dev d2 a1 B2
835
836 resolution: no need to switch
837
838case 7
839
840 uc->dev d1 (a1), d2 (a2) B1, B2
841 new_uc->dev d1 B1
842
843 resolution: no need to switch
844
845*/
846static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
847 struct audio_usecase *new_uc,
848 snd_device_t new_snd_device)
849{
850 audio_devices_t a1 = uc->stream.out->devices;
851 audio_devices_t a2 = new_uc->stream.out->devices;
852
853 snd_device_t d1 = uc->out_snd_device;
854 snd_device_t d2 = new_snd_device;
855
856 // Treat as a special case when a1 and a2 are not disjoint
857 if ((a1 != a2) && (a1 & a2)) {
858 snd_device_t d3[2];
859 int num_devices = 0;
860 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
861 &num_devices,
862 d3);
863 if (ret < 0) {
864 if (ret != -ENOSYS) {
865 ALOGW("%s failed to split snd_device %d",
866 __func__,
867 popcount(a1) > 1 ? d1 : d2);
868 }
869 goto end;
870 }
871
872 // NB: case 7 is hypothetical and isn't a practical usecase yet.
873 // But if it does happen, we need to give priority to d2 if
874 // the combo devices active on the existing usecase share a backend.
875 // This is because we cannot have a usecase active on a combo device
876 // and a new usecase requests one device in this combo pair.
877 if (platform_check_backends_match(d3[0], d3[1])) {
878 return d2; // case 5
879 } else {
880 return d1; // case 1
881 }
882 } else {
883 if (platform_check_backends_match(d1, d2)) {
884 return d2; // case 2, 4
885 } else {
886 return d1; // case 6, 3
887 }
888 }
889
890end:
891 return d2; // return whatever was calculated before.
892}
893
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700894static void check_and_route_playback_usecases(struct audio_device *adev,
895 struct audio_usecase *uc_info,
896 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897{
898 struct listnode *node;
899 struct audio_usecase *usecase;
900 bool switch_device[AUDIO_USECASE_MAX];
901 int i, num_uc_to_switch = 0;
902
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700903 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
904 uc_info,
905 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700906
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
912 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800913 audio_extn_a2dp_is_force_device_switch()) {
914 force_routing = true;
915 }
916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 /*
918 * This function is to make sure that all the usecases that are active on
919 * the hardware codec backend are always routed to any one device that is
920 * handled by the hardware codec.
921 * For example, if low-latency and deep-buffer usecases are currently active
922 * on speaker and out_set_parameters(headset) is received on low-latency
923 * output, then we have to make sure deep-buffer is also switched to headset,
924 * because of the limitation that both the devices cannot be enabled
925 * at the same time as they share the same backend.
926 */
927 /* Disable all the usecases on the shared backend other than the
928 specified usecase */
929 for (i = 0; i < AUDIO_USECASE_MAX; i++)
930 switch_device[i] = false;
931
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700934 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
935 continue;
936
937 if (force_routing ||
938 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700939 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
940 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700941 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700944 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900956 }
957 }
958
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700959 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700963 d_device = derive_playback_snd_device(usecase, uc_info,
964 snd_device);
965 enable_snd_device(adev, d_device);
966 /* Update the out_snd_device before enabling the audio route */
967 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 }
969 }
970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Re-route all the usecases on the shared backend other than the
972 specified usecase to new snd devices */
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700976 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 }
978 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980}
981
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700982static void check_and_route_capture_usecases(struct audio_device *adev,
983 struct audio_usecase *uc_info,
984 snd_device_t snd_device)
985{
986 struct listnode *node;
987 struct audio_usecase *usecase;
988 bool switch_device[AUDIO_USECASE_MAX];
989 int i, num_uc_to_switch = 0;
990
vivek mehta4ed66e62016-04-15 23:33:34 -0700991 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
992
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 /*
994 * This function is to make sure that all the active capture usecases
995 * are always routed to the same input sound device.
996 * For example, if audio-record and voice-call usecases are currently
997 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
998 * is received for voice call then we have to make sure that audio-record
999 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1000 * because of the limitation that two devices cannot be enabled
1001 * at the same time if they share the same backend.
1002 */
1003 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1004 switch_device[i] = false;
1005
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
1008 if (usecase->type != PCM_PLAYBACK &&
1009 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001010 usecase->in_snd_device != snd_device &&
1011 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001012 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1013 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001014 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001015 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001016 switch_device[usecase->id] = true;
1017 num_uc_to_switch++;
1018 }
1019 }
1020
1021 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 list_for_each(node, &adev->usecase_list) {
1023 usecase = node_to_item(node, struct audio_usecase, list);
1024 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001026 }
1027 }
1028
1029 list_for_each(node, &adev->usecase_list) {
1030 usecase = node_to_item(node, struct audio_usecase, list);
1031 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001032 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001033 }
1034 }
1035
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 /* Re-route all the usecases on the shared backend other than the
1037 specified usecase to new snd devices */
1038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
1040 /* Update the in_snd_device only before enabling the audio route */
1041 if (switch_device[usecase->id] ) {
1042 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001043 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001044 }
1045 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 }
1047}
1048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001050static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001052 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001053 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054
1055 switch (channels) {
1056 /*
1057 * Do not handle stereo output in Multi-channel cases
1058 * Stereo case is handled in normal playback path
1059 */
1060 case 6:
1061 ALOGV("%s: HDMI supports 5.1", __func__);
1062 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1063 break;
1064 case 8:
1065 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1066 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1067 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1068 break;
1069 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001070 ALOGE("HDMI does not support multi channel playback");
1071 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 break;
1073 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075}
1076
Andy Hung18859412017-08-09 11:47:21 -07001077static ssize_t read_usb_sup_sample_rates(bool is_playback,
1078 uint32_t *supported_sample_rates,
1079 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001080{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001081 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1082 supported_sample_rates,
1083 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001084#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001085 for (ssize_t i=0; i<count; i++) {
1086 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1087 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001088 }
1089#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001090 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001091}
1092
Haynes Mathew George569b7482017-05-08 14:44:27 -07001093static int read_usb_sup_channel_masks(bool is_playback,
1094 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001095 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001096{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001097 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001098 int channel_count;
1099 uint32_t num_masks = 0;
1100 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1101 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001102 }
Eric Laurent74b55762017-07-09 17:04:53 -07001103 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001104 // start from 2 channels as framework currently doesn't support mono.
1105 // TODO: consider only supporting channel index masks beyond stereo here.
1106 for (channel_count = FCC_2;
1107 channel_count <= channels && num_masks < max_masks;
1108 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001109 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1110 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001111 for (channel_count = FCC_2;
1112 channel_count <= channels && num_masks < max_masks;
1113 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001114 supported_channel_masks[num_masks++] =
1115 audio_channel_mask_for_index_assignment_from_count(channel_count);
1116 }
1117 } else {
1118 // For capture we report all supported channel masks from 1 channel up.
1119 channel_count = MIN_CHANNEL_COUNT;
1120 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1121 // indexed mask
1122 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1123 supported_channel_masks[num_masks++] =
1124 audio_channel_in_mask_from_count(channel_count);
1125 }
1126 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001127#ifdef NDEBUG
1128 for (size_t i = 0; i < num_masks; ++i) {
1129 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1130 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1131 }
1132#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001133 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001134}
1135
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001136static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001137 audio_format_t *supported_formats,
1138 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001139{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001140 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001141 switch (bitwidth) {
1142 case 24:
1143 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001144 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001145 break;
1146 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001148 break;
1149 case 16:
1150 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001152 break;
1153 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 ALOGV("%s: %s supported format %d", __func__,
1155 is_playback ? "P" : "C", bitwidth);
1156 return 1;
1157}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001158
Haynes Mathew George569b7482017-05-08 14:44:27 -07001159static int read_usb_sup_params_and_compare(bool is_playback,
1160 audio_format_t *format,
1161 audio_format_t *supported_formats,
1162 uint32_t max_formats,
1163 audio_channel_mask_t *mask,
1164 audio_channel_mask_t *supported_channel_masks,
1165 uint32_t max_masks,
1166 uint32_t *rate,
1167 uint32_t *supported_sample_rates,
1168 uint32_t max_rates) {
1169 int ret = 0;
1170 int num_formats;
1171 int num_masks;
1172 int num_rates;
1173 int i;
1174
1175 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1176 max_formats);
1177 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1178 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001179
Haynes Mathew George569b7482017-05-08 14:44:27 -07001180 num_rates = read_usb_sup_sample_rates(is_playback,
1181 supported_sample_rates, max_rates);
1182
1183#define LUT(table, len, what, dflt) \
1184 for (i=0; i<len && (table[i] != what); i++); \
1185 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1186
1187 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1188 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1189 LUT(supported_sample_rates, num_rates, *rate, 0);
1190
1191#undef LUT
1192 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001193}
1194
Andy Hungd9653bd2017-08-01 19:31:39 -07001195static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1196{
1197 // Check if usb is ready.
1198 // The usb device may have been removed quickly after insertion and hence
1199 // no longer available. This will show up as empty channel masks, or rates.
1200
1201 pthread_mutex_lock(&adev->lock);
1202 uint32_t supported_sample_rate;
1203
1204 // we consider usb ready if we can fetch at least one sample rate.
1205 const bool ready = read_usb_sup_sample_rates(
1206 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1207 pthread_mutex_unlock(&adev->lock);
1208 return ready;
1209}
1210
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001211static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1212{
1213 struct audio_usecase *usecase;
1214 struct listnode *node;
1215
1216 list_for_each(node, &adev->usecase_list) {
1217 usecase = node_to_item(node, struct audio_usecase, list);
1218 if (usecase->type == VOICE_CALL) {
1219 ALOGV("%s: usecase id %d", __func__, usecase->id);
1220 return usecase->id;
1221 }
1222 }
1223 return USECASE_INVALID;
1224}
1225
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001226struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1227 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228{
1229 struct audio_usecase *usecase;
1230 struct listnode *node;
1231
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (usecase->id == uc_id)
1235 return usecase;
1236 }
1237 return NULL;
1238}
1239
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001240static bool force_device_switch(struct audio_usecase *usecase)
1241{
1242 if (usecase->stream.out == NULL) {
1243 ALOGE("%s: stream.out is NULL", __func__);
1244 return false;
1245 }
1246
1247 // Force all A2DP output devices to reconfigure for proper AFE encode format
1248 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1249 // in suspended state, hence try to trigger a retry when we again get a routing request.
1250 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1251 audio_extn_a2dp_is_force_device_switch()) {
1252 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1253 return true;
1254 }
1255
1256 return false;
1257}
1258
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001259int select_devices(struct audio_device *adev,
1260 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001262 snd_device_t out_snd_device = SND_DEVICE_NONE;
1263 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001264 struct audio_usecase *usecase = NULL;
1265 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001266 struct audio_usecase *hfp_usecase = NULL;
1267 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001268 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001270 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1271 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 usecase = get_usecase_from_list(adev, uc_id);
1274 if (usecase == NULL) {
1275 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1276 return -EINVAL;
1277 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001279 if ((usecase->type == VOICE_CALL) ||
1280 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001281 out_snd_device = platform_get_output_snd_device(adev->platform,
1282 usecase->stream.out->devices);
1283 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase->devices = usecase->stream.out->devices;
1285 } else {
1286 /*
1287 * If the voice call is active, use the sound devices of voice call usecase
1288 * so that it would not result any device switch. All the usecases will
1289 * be switched to new device when select_devices() is called for voice call
1290 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001291 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001293 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001294 vc_usecase = get_usecase_from_list(adev,
1295 get_voice_usecase_id_from_list(adev));
1296 if ((vc_usecase != NULL) &&
1297 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1298 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 in_snd_device = vc_usecase->in_snd_device;
1300 out_snd_device = vc_usecase->out_snd_device;
1301 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001302 } else if (audio_extn_hfp_is_active(adev)) {
1303 hfp_ucid = audio_extn_hfp_get_usecase();
1304 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1305 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1306 in_snd_device = hfp_usecase->in_snd_device;
1307 out_snd_device = hfp_usecase->out_snd_device;
1308 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 }
1310 if (usecase->type == PCM_PLAYBACK) {
1311 usecase->devices = usecase->stream.out->devices;
1312 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001313 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001314 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001315
Eric Laurentb23d5282013-05-14 15:27:20 -07001316 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001318
1319 if (voip_usecase)
1320 voip_out = voip_usecase->stream.out;
1321
1322 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001324 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001325 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001326 select_devices(adev, adev->active_input->usecase);
1327 }
1328 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 } else if (usecase->type == PCM_CAPTURE) {
1330 usecase->devices = usecase->stream.in->device;
1331 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001332 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001333 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001334 if (adev->active_input &&
1335 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1336 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001337
1338 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1339 USECASE_AUDIO_PLAYBACK_VOIP);
1340
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001341 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001342 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1343 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001344 } else if (voip_usecase) {
1345 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001346 } else if (adev->primary_output) {
1347 out_device = adev->primary_output->devices;
1348 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001349 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001350 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001351 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 }
1353 }
1354
1355 if (out_snd_device == usecase->out_snd_device &&
1356 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001357 if (!force_device_switch(usecase))
1358 return 0;
1359 }
1360
1361 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1362 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1363 return 0;
1364 }
1365
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001366 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1367 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001368 (!audio_extn_a2dp_is_ready())) {
1369 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001370 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1371 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1372 else
1373 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 }
1375
juyuchen66c4ecf2018-08-06 15:39:34 +08001376 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1377 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1378 }
1379
Eric Laurent2bafff12016-03-17 12:17:23 -07001380 if (out_snd_device != SND_DEVICE_NONE &&
1381 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1382 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1383 __func__,
1384 use_case_table[uc_id],
1385 adev->last_logged_snd_device[uc_id][0],
1386 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1387 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1388 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1389 -1,
1390 out_snd_device,
1391 platform_get_snd_device_name(out_snd_device),
1392 platform_get_snd_device_acdb_id(out_snd_device));
1393 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1394 }
1395 if (in_snd_device != SND_DEVICE_NONE &&
1396 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1397 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1398 __func__,
1399 use_case_table[uc_id],
1400 adev->last_logged_snd_device[uc_id][1],
1401 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1402 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1403 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1404 -1,
1405 in_snd_device,
1406 platform_get_snd_device_name(in_snd_device),
1407 platform_get_snd_device_acdb_id(in_snd_device));
1408 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1409 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411 /*
1412 * Limitation: While in call, to do a device switch we need to disable
1413 * and enable both RX and TX devices though one of them is same as current
1414 * device.
1415 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001416 if ((usecase->type == VOICE_CALL) &&
1417 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1418 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001419 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001420 /* Disable sidetone only if voice call already exists */
1421 if (voice_is_call_state_active(adev))
1422 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001423 }
1424
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001425 /* Disable current sound devices */
1426 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001427 disable_audio_route(adev, usecase);
1428 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 }
1430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001432 disable_audio_route(adev, usecase);
1433 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 }
1435
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001436 /* Applicable only on the targets that has external modem.
1437 * New device information should be sent to modem before enabling
1438 * the devices to reduce in-call device switch time.
1439 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001440 if ((usecase->type == VOICE_CALL) &&
1441 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1442 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001443 status = platform_switch_voice_call_enable_device_config(adev->platform,
1444 out_snd_device,
1445 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001446 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 /* Enable new sound devices */
1449 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001450 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001451 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1452 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001453 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001454 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 }
1456
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001457 if (in_snd_device != SND_DEVICE_NONE) {
1458 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001459 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001460 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461
Eric Laurentb23d5282013-05-14 15:27:20 -07001462 if (usecase->type == VOICE_CALL)
1463 status = platform_switch_voice_call_device_post(adev->platform,
1464 out_snd_device,
1465 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001466
sangwoo170731f2013-06-08 15:36:36 +09001467 usecase->in_snd_device = in_snd_device;
1468 usecase->out_snd_device = out_snd_device;
1469
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001470 audio_extn_tfa_98xx_set_mode();
1471
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001472 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001473
Jasmine Cha70771b62018-05-15 15:02:43 +08001474 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001475
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001476 /* Applicable only on the targets that has external modem.
1477 * Enable device command should be sent to modem only after
1478 * enabling voice call mixer controls
1479 */
vivek mehta765eb642015-08-07 19:46:06 -07001480 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001481 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1482 out_snd_device,
1483 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001484 /* Enable sidetone only if voice call already exists */
1485 if (voice_is_call_state_active(adev))
1486 voice_set_sidetone(adev, out_snd_device, true);
1487 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001488
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001489 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001490 struct stream_out *voip_out = voip_usecase->stream.out;
1491 audio_extn_utils_send_app_type_gain(adev,
1492 voip_out->app_type_cfg.app_type,
1493 &voip_out->app_type_cfg.gain[0]);
1494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 return status;
1496}
1497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498static int stop_input_stream(struct stream_in *in)
1499{
1500 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 struct audio_usecase *uc_info;
1502 struct audio_device *adev = in->dev;
1503
Eric Laurent994a6932013-07-17 11:51:42 -07001504 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001506
1507 if (adev->active_input) {
1508 if (adev->active_input->usecase == in->usecase) {
1509 adev->active_input = NULL;
1510 } else {
1511 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1512 __func__,
1513 use_case_table[adev->active_input->usecase],
1514 use_case_table[in->usecase]);
1515 }
1516 }
1517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 uc_info = get_usecase_from_list(adev, in->usecase);
1519 if (uc_info == NULL) {
1520 ALOGE("%s: Could not find the usecase (%d) in the list",
1521 __func__, in->usecase);
1522 return -EINVAL;
1523 }
1524
vivek mehta781065c2017-04-04 12:55:01 -07001525 /* Close in-call recording streams */
1526 voice_check_and_stop_incall_rec_usecase(adev, in);
1527
Eric Laurent150dbfe2013-02-27 14:31:02 -08001528 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001529 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530
1531 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001532 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001534 list_remove(&uc_info->list);
1535 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536
Eric Laurent994a6932013-07-17 11:51:42 -07001537 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 return ret;
1539}
1540
1541int start_input_stream(struct stream_in *in)
1542{
1543 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001544 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 struct audio_usecase *uc_info;
1546 struct audio_device *adev = in->dev;
1547
Eric Laurent994a6932013-07-17 11:51:42 -07001548 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001549
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001550 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1551 return -EIO;
1552
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001553 if (in->card_status == CARD_STATUS_OFFLINE ||
1554 adev->card_status == CARD_STATUS_OFFLINE) {
1555 ALOGW("in->card_status or adev->card_status offline, try again");
1556 ret = -EAGAIN;
1557 goto error_config;
1558 }
1559
vivek mehta781065c2017-04-04 12:55:01 -07001560 /* Check if source matches incall recording usecase criteria */
1561 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1562 if (ret)
1563 goto error_config;
1564 else
1565 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1566
Eric Laurentb23d5282013-05-14 15:27:20 -07001567 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 if (in->pcm_device_id < 0) {
1569 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1570 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001571 ret = -EINVAL;
1572 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574
1575 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1577 uc_info->id = in->usecase;
1578 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001579 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 uc_info->devices = in->device;
1581 uc_info->in_snd_device = SND_DEVICE_NONE;
1582 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001584 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001585
Wei Wangf4837d52017-11-21 14:51:20 -08001586 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001587 audio_extn_perf_lock_acquire();
1588
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Eric Laurent0e46adf2016-12-16 12:49:24 -08001591 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001592 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001593 ALOGE("%s: pcm stream not ready", __func__);
1594 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001595 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001596 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001597 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001598 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1599 goto error_open;
1600 }
1601 } else {
1602 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1603 unsigned int pcm_open_retry_count = 0;
1604
1605 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1606 flags |= PCM_MMAP | PCM_NOIRQ;
1607 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1608 } else if (in->realtime) {
1609 flags |= PCM_MMAP | PCM_NOIRQ;
1610 }
1611
1612 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1613 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1614
1615 while (1) {
1616 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1617 flags, &in->config);
1618 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1619 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1620 if (in->pcm != NULL) {
1621 pcm_close(in->pcm);
1622 in->pcm = NULL;
1623 }
1624 if (pcm_open_retry_count-- == 0) {
1625 ret = -EIO;
1626 goto error_open;
1627 }
1628 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1629 continue;
1630 }
1631 break;
1632 }
1633
1634 ALOGV("%s: pcm_prepare", __func__);
1635 ret = pcm_prepare(in->pcm);
1636 if (ret < 0) {
1637 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001638 pcm_close(in->pcm);
1639 in->pcm = NULL;
1640 goto error_open;
1641 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001642 if (in->realtime) {
1643 ret = pcm_start(in->pcm);
1644 if (ret < 0) {
1645 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1646 pcm_close(in->pcm);
1647 in->pcm = NULL;
1648 goto error_open;
1649 }
1650 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001651 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001652 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001653 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001654 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001655 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001656
Eric Laurent0e46adf2016-12-16 12:49:24 -08001657 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001658
1659error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001661 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001662 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001663
1664error_config:
1665 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001666 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001667 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668}
1669
Eric Laurenta1478072015-09-21 17:21:52 -07001670void lock_input_stream(struct stream_in *in)
1671{
1672 pthread_mutex_lock(&in->pre_lock);
1673 pthread_mutex_lock(&in->lock);
1674 pthread_mutex_unlock(&in->pre_lock);
1675}
1676
1677void lock_output_stream(struct stream_out *out)
1678{
1679 pthread_mutex_lock(&out->pre_lock);
1680 pthread_mutex_lock(&out->lock);
1681 pthread_mutex_unlock(&out->pre_lock);
1682}
1683
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684/* must be called with out->lock locked */
1685static int send_offload_cmd_l(struct stream_out* out, int command)
1686{
1687 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1688
1689 ALOGVV("%s %d", __func__, command);
1690
1691 cmd->cmd = command;
1692 list_add_tail(&out->offload_cmd_list, &cmd->node);
1693 pthread_cond_signal(&out->offload_cond);
1694 return 0;
1695}
1696
1697/* must be called iwth out->lock locked */
1698static void stop_compressed_output_l(struct stream_out *out)
1699{
1700 out->offload_state = OFFLOAD_STATE_IDLE;
1701 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001702 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001703 if (out->compr != NULL) {
1704 compress_stop(out->compr);
1705 while (out->offload_thread_blocked) {
1706 pthread_cond_wait(&out->cond, &out->lock);
1707 }
1708 }
1709}
1710
1711static void *offload_thread_loop(void *context)
1712{
1713 struct stream_out *out = (struct stream_out *) context;
1714 struct listnode *item;
1715
1716 out->offload_state = OFFLOAD_STATE_IDLE;
1717 out->playback_started = 0;
1718
1719 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1720 set_sched_policy(0, SP_FOREGROUND);
1721 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1722
1723 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001724 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 for (;;) {
1726 struct offload_cmd *cmd = NULL;
1727 stream_callback_event_t event;
1728 bool send_callback = false;
1729
1730 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1731 __func__, list_empty(&out->offload_cmd_list),
1732 out->offload_state);
1733 if (list_empty(&out->offload_cmd_list)) {
1734 ALOGV("%s SLEEPING", __func__);
1735 pthread_cond_wait(&out->offload_cond, &out->lock);
1736 ALOGV("%s RUNNING", __func__);
1737 continue;
1738 }
1739
1740 item = list_head(&out->offload_cmd_list);
1741 cmd = node_to_item(item, struct offload_cmd, node);
1742 list_remove(item);
1743
1744 ALOGVV("%s STATE %d CMD %d out->compr %p",
1745 __func__, out->offload_state, cmd->cmd, out->compr);
1746
1747 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1748 free(cmd);
1749 break;
1750 }
1751
1752 if (out->compr == NULL) {
1753 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001754 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 pthread_cond_signal(&out->cond);
1756 continue;
1757 }
1758 out->offload_thread_blocked = true;
1759 pthread_mutex_unlock(&out->lock);
1760 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001761 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1763 compress_wait(out->compr, -1);
1764 send_callback = true;
1765 event = STREAM_CBK_EVENT_WRITE_READY;
1766 break;
1767 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001768 compress_next_track(out->compr);
1769 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 send_callback = true;
1771 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001772 /* Resend the metadata for next iteration */
1773 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 break;
1775 case OFFLOAD_CMD_DRAIN:
1776 compress_drain(out->compr);
1777 send_callback = true;
1778 event = STREAM_CBK_EVENT_DRAIN_READY;
1779 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001780 case OFFLOAD_CMD_ERROR:
1781 send_callback = true;
1782 event = STREAM_CBK_EVENT_ERROR;
1783 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 default:
1785 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1786 break;
1787 }
Eric Laurenta1478072015-09-21 17:21:52 -07001788 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 out->offload_thread_blocked = false;
1790 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001791 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001792 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001794 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 free(cmd);
1796 }
1797
1798 pthread_cond_signal(&out->cond);
1799 while (!list_empty(&out->offload_cmd_list)) {
1800 item = list_head(&out->offload_cmd_list);
1801 list_remove(item);
1802 free(node_to_item(item, struct offload_cmd, node));
1803 }
1804 pthread_mutex_unlock(&out->lock);
1805
1806 return NULL;
1807}
1808
1809static int create_offload_callback_thread(struct stream_out *out)
1810{
1811 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1812 list_init(&out->offload_cmd_list);
1813 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1814 offload_thread_loop, out);
1815 return 0;
1816}
1817
1818static int destroy_offload_callback_thread(struct stream_out *out)
1819{
Eric Laurenta1478072015-09-21 17:21:52 -07001820 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001821 stop_compressed_output_l(out);
1822 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1823
1824 pthread_mutex_unlock(&out->lock);
1825 pthread_join(out->offload_thread, (void **) NULL);
1826 pthread_cond_destroy(&out->offload_cond);
1827
1828 return 0;
1829}
1830
Eric Laurent07eeafd2013-10-06 12:52:49 -07001831static bool allow_hdmi_channel_config(struct audio_device *adev)
1832{
1833 struct listnode *node;
1834 struct audio_usecase *usecase;
1835 bool ret = true;
1836
1837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
1839 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1840 /*
1841 * If voice call is already existing, do not proceed further to avoid
1842 * disabling/enabling both RX and TX devices, CSD calls, etc.
1843 * Once the voice call done, the HDMI channels can be configured to
1844 * max channels of remaining use cases.
1845 */
1846 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001847 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001848 __func__);
1849 ret = false;
1850 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001851 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1852 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001853 "no change in HDMI channels", __func__);
1854 ret = false;
1855 break;
1856 }
1857 }
1858 }
1859 return ret;
1860}
1861
1862static int check_and_set_hdmi_channels(struct audio_device *adev,
1863 unsigned int channels)
1864{
1865 struct listnode *node;
1866 struct audio_usecase *usecase;
1867
1868 /* Check if change in HDMI channel config is allowed */
1869 if (!allow_hdmi_channel_config(adev))
1870 return 0;
1871
1872 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001873 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001874 return 0;
1875 }
1876
1877 platform_set_hdmi_channels(adev->platform, channels);
1878 adev->cur_hdmi_channels = channels;
1879
1880 /*
1881 * Deroute all the playback streams routed to HDMI so that
1882 * the back end is deactivated. Note that backend will not
1883 * be deactivated if any one stream is connected to it.
1884 */
1885 list_for_each(node, &adev->usecase_list) {
1886 usecase = node_to_item(node, struct audio_usecase, list);
1887 if (usecase->type == PCM_PLAYBACK &&
1888 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001889 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001890 }
1891 }
1892
1893 /*
1894 * Enable all the streams disabled above. Now the HDMI backend
1895 * will be activated with new channel configuration
1896 */
1897 list_for_each(node, &adev->usecase_list) {
1898 usecase = node_to_item(node, struct audio_usecase, list);
1899 if (usecase->type == PCM_PLAYBACK &&
1900 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001901 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001902 }
1903 }
1904
1905 return 0;
1906}
1907
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001908static int check_and_set_usb_service_interval(struct audio_device *adev,
1909 struct audio_usecase *uc_info,
1910 bool min)
1911{
1912 struct listnode *node;
1913 struct audio_usecase *usecase;
1914 bool switch_usecases = false;
1915 bool reconfig = false;
1916
1917 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1918 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1919 return -1;
1920
1921 /* set if the valid usecase do not already exist */
1922 list_for_each(node, &adev->usecase_list) {
1923 usecase = node_to_item(node, struct audio_usecase, list);
1924 if (usecase->type == PCM_PLAYBACK &&
1925 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1926 switch (usecase->id) {
1927 case USECASE_AUDIO_PLAYBACK_MMAP:
1928 case USECASE_AUDIO_PLAYBACK_ULL:
1929 // cannot reconfig while mmap/ull is present.
1930 return -1;
1931 default:
1932 switch_usecases = true;
1933 break;
1934 }
1935 }
1936 if (switch_usecases)
1937 break;
1938 }
1939 /*
1940 * client can try to set service interval in start_output_stream
1941 * to min or to 0 (i.e reset) in stop_output_stream .
1942 */
1943 unsigned long service_interval =
1944 audio_extn_usb_find_service_interval(min, true /*playback*/);
1945 int ret = platform_set_usb_service_interval(adev->platform,
1946 true /*playback*/,
1947 service_interval,
1948 &reconfig);
1949 /* no change or not supported or no active usecases */
1950 if (ret || !reconfig || !switch_usecases)
1951 return -1;
1952 return 0;
1953#undef VALID_USECASE
1954}
1955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956static int stop_output_stream(struct stream_out *out)
1957{
1958 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 struct audio_usecase *uc_info;
1960 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001961 bool has_voip_usecase =
1962 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963
Eric Laurent994a6932013-07-17 11:51:42 -07001964 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001965 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 uc_info = get_usecase_from_list(adev, out->usecase);
1967 if (uc_info == NULL) {
1968 ALOGE("%s: Could not find the usecase (%d) in the list",
1969 __func__, out->usecase);
1970 return -EINVAL;
1971 }
1972
Haynes Mathew George41f86652014-06-17 14:22:15 -07001973 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1974 if (adev->visualizer_stop_output != NULL)
1975 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1976 if (adev->offload_effects_stop_output != NULL)
1977 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001978 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1979 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1980 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001981 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001982
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07001983 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
1984 voice_set_device_mute_flag(adev, false);
1985
Eric Laurent150dbfe2013-02-27 14:31:02 -08001986 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001987 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001988
1989 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001990 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001992 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993
Eric Laurent0499d4f2014-08-25 22:39:29 -05001994 audio_extn_extspk_update(adev->extspk);
1995
Eric Laurent07eeafd2013-10-06 12:52:49 -07001996 /* Must be called after removing the usecase from list */
1997 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1998 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08001999 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002000 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2001 if (ret == 0) {
2002 /* default service interval was successfully updated,
2003 reopen USB backend with new service interval */
2004 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2005 }
2006 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002007 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002008
HW Lee88512e92018-06-12 15:26:09 +08002009 if (has_voip_usecase ||
2010 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2011 struct listnode *node;
2012 struct audio_usecase *usecase;
2013 list_for_each(node, &adev->usecase_list) {
2014 usecase = node_to_item(node, struct audio_usecase, list);
2015 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2016 continue;
2017
2018 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2019 __func__, usecase->id, use_case_table[usecase->id],
2020 out->usecase, use_case_table[out->usecase]);
2021 select_devices(adev, usecase->id);
2022 }
2023 }
2024
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002025 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002026 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 return ret;
2028}
2029
2030int start_output_stream(struct stream_out *out)
2031{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033 struct audio_usecase *uc_info;
2034 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002035 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036
Eric Laurent994a6932013-07-17 11:51:42 -07002037 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002038 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002039
2040 if (out->card_status == CARD_STATUS_OFFLINE ||
2041 adev->card_status == CARD_STATUS_OFFLINE) {
2042 ALOGW("out->card_status or adev->card_status offline, try again");
2043 ret = -EAGAIN;
2044 goto error_config;
2045 }
2046
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002047 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2048 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002049 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002050 a2dp_combo = true;
2051 } else {
2052 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2053 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2054 ret = -EAGAIN;
2055 goto error_config;
2056 }
2057 }
2058 }
2059 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002060 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061 if (out->pcm_device_id < 0) {
2062 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2063 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002064 ret = -EINVAL;
2065 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 }
2067
2068 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2069 uc_info->id = out->usecase;
2070 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002071 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002072 uc_info->devices = out->devices;
2073 uc_info->in_snd_device = SND_DEVICE_NONE;
2074 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075
Eric Laurent07eeafd2013-10-06 12:52:49 -07002076 /* This must be called before adding this usecase to the list */
2077 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2078 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002079 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2080 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2081 /* USB backend is not reopened immediately.
2082 This is eventually done as part of select_devices */
2083 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002084
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002085 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086
Wei Wangf4837d52017-11-21 14:51:20 -08002087 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002088 audio_extn_perf_lock_acquire();
2089
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002090 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2091 (!audio_extn_a2dp_is_ready())) {
2092 if (!a2dp_combo) {
2093 check_a2dp_restore_l(adev, out, false);
2094 } else {
2095 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002096 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2097 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2098 else
2099 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002100 select_devices(adev, out->usecase);
2101 out->devices = dev;
2102 }
2103 } else {
2104 select_devices(adev, out->usecase);
2105 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002106
Eric Laurent0499d4f2014-08-25 22:39:29 -05002107 audio_extn_extspk_update(adev->extspk);
2108
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002109 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2110 voice_set_device_mute_flag(adev, true);
2111
Andy Hung31aca912014-03-20 17:14:59 -07002112 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002113 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002114 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2115 out->pcm = NULL;
2116 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2117 COMPRESS_IN, &out->compr_config);
2118 if (out->compr && !is_compress_ready(out->compr)) {
2119 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2120 compress_close(out->compr);
2121 out->compr = NULL;
2122 ret = -EIO;
2123 goto error_open;
2124 }
2125 if (out->offload_callback)
2126 compress_nonblock(out->compr, out->non_blocking);
2127
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002128 if (adev->visualizer_start_output != NULL) {
2129 int capture_device_id =
2130 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2131 PCM_CAPTURE);
2132 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2133 adev->snd_card, capture_device_id);
2134 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002135 if (adev->offload_effects_start_output != NULL)
2136 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2137 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002138 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002139 ALOGE("%s: pcm stream not ready", __func__);
2140 goto error_open;
2141 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002142 ret = pcm_start(out->pcm);
2143 if (ret < 0) {
2144 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2145 goto error_open;
2146 }
2147 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002148 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002149 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002150
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002151 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2152 flags |= PCM_MMAP | PCM_NOIRQ;
2153 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002154 } else if (out->realtime) {
2155 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002156 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002157
2158 while (1) {
2159 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2160 flags, &out->config);
2161 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2162 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2163 if (out->pcm != NULL) {
2164 pcm_close(out->pcm);
2165 out->pcm = NULL;
2166 }
2167 if (pcm_open_retry_count-- == 0) {
2168 ret = -EIO;
2169 goto error_open;
2170 }
2171 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2172 continue;
2173 }
2174 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002176 ALOGV("%s: pcm_prepare", __func__);
2177 if (pcm_is_ready(out->pcm)) {
2178 ret = pcm_prepare(out->pcm);
2179 if (ret < 0) {
2180 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2181 pcm_close(out->pcm);
2182 out->pcm = NULL;
2183 goto error_open;
2184 }
2185 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002186 if (out->realtime) {
2187 ret = pcm_start(out->pcm);
2188 if (ret < 0) {
2189 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2190 pcm_close(out->pcm);
2191 out->pcm = NULL;
2192 goto error_open;
2193 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002194 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002195 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002196 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002197 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002198 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002199 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002200
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002201 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2202 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2203 audio_low_latency_hint_start();
2204 }
2205
vivek mehtae59cfb22017-06-16 15:57:11 -07002206 // consider a scenario where on pause lower layers are tear down.
2207 // so on resume, swap mixer control need to be sent only when
2208 // backend is active, hence rather than sending from enable device
2209 // sending it from start of streamtream
2210
2211 platform_set_swap_channels(adev, true);
2212
Eric Laurent994a6932013-07-17 11:51:42 -07002213 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002214 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002216 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002217 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002219error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002220 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221}
2222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223static int check_input_parameters(uint32_t sample_rate,
2224 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002225 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002227 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2228 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002229 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2230 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002231 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2232 return -EINVAL;
2233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234
Eric Laurent74b55762017-07-09 17:04:53 -07002235 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2236 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002237 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002238 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002239 return -EINVAL;
2240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241
2242 switch (sample_rate) {
2243 case 8000:
2244 case 11025:
2245 case 12000:
2246 case 16000:
2247 case 22050:
2248 case 24000:
2249 case 32000:
2250 case 44100:
2251 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002252 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253 break;
2254 default:
vivek mehtadae44712015-07-27 14:13:18 -07002255 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 return -EINVAL;
2257 }
2258
2259 return 0;
2260}
2261
Kevin Rocarda325aa22018-04-03 09:15:52 -07002262/** Add a value in a list if not already present.
2263 * @return true if value was successfully inserted or already present,
2264 * false if the list is full and does not contain the value.
2265 */
2266static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2267 for (size_t i = 0; i < list_length; i++) {
2268 if (list[i] == value) return true; // value is already present
2269 if (list[i] == 0) { // no values in this slot
2270 list[i] = value;
2271 return true; // value inserted
2272 }
2273 }
2274 return false; // could not insert value
2275}
2276
2277/** Add channel_mask in supported_channel_masks if not already present.
2278 * @return true if channel_mask was successfully inserted or already present,
2279 * false if supported_channel_masks is full and does not contain channel_mask.
2280 */
2281static void register_channel_mask(audio_channel_mask_t channel_mask,
2282 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2283 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2284 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2285}
2286
2287/** Add format in supported_formats if not already present.
2288 * @return true if format was successfully inserted or already present,
2289 * false if supported_formats is full and does not contain format.
2290 */
2291static void register_format(audio_format_t format,
2292 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2293 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2294 "%s: stream can not declare supporting its format %x", __func__, format);
2295}
2296/** Add sample_rate in supported_sample_rates if not already present.
2297 * @return true if sample_rate was successfully inserted or already present,
2298 * false if supported_sample_rates is full and does not contain sample_rate.
2299 */
2300static void register_sample_rate(uint32_t sample_rate,
2301 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2302 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2303 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2304}
2305
vivek mehtaa68fea62017-06-08 19:04:02 -07002306static size_t get_stream_buffer_size(size_t duration_ms,
2307 uint32_t sample_rate,
2308 audio_format_t format,
2309 int channel_count,
2310 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002311{
2312 size_t size = 0;
2313
vivek mehtaa68fea62017-06-08 19:04:02 -07002314 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002315 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002316 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002317
2318 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319
Glenn Kasten4f993392014-05-14 07:30:48 -07002320 /* make sure the size is multiple of 32 bytes
2321 * At 48 kHz mono 16-bit PCM:
2322 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2323 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2324 */
2325 size += 0x1f;
2326 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002327
2328 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329}
2330
2331static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2332{
2333 struct stream_out *out = (struct stream_out *)stream;
2334
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002335 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336}
2337
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002338static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339{
2340 return -ENOSYS;
2341}
2342
2343static size_t out_get_buffer_size(const struct audio_stream *stream)
2344{
2345 struct stream_out *out = (struct stream_out *)stream;
2346
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2348 return out->compr_config.fragment_size;
2349 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002350 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002351 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352}
2353
2354static uint32_t out_get_channels(const struct audio_stream *stream)
2355{
2356 struct stream_out *out = (struct stream_out *)stream;
2357
2358 return out->channel_mask;
2359}
2360
2361static audio_format_t out_get_format(const struct audio_stream *stream)
2362{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 struct stream_out *out = (struct stream_out *)stream;
2364
2365 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366}
2367
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002368static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 return -ENOSYS;
2371}
2372
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002373/* must be called with out->lock locked */
2374static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375{
2376 struct stream_out *out = (struct stream_out *)stream;
2377 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002378 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002380 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002381 if (adev->adm_deregister_stream)
2382 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002383 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002385 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2386 if (out->pcm) {
2387 pcm_close(out->pcm);
2388 out->pcm = NULL;
2389 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002390 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002391 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002392 out->playback_started = false;
2393 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 } else {
2395 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002396 out->gapless_mdata.encoder_delay = 0;
2397 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002398 if (out->compr != NULL) {
2399 compress_close(out->compr);
2400 out->compr = NULL;
2401 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002402 }
Phil Burkbc991042017-02-24 08:06:44 -08002403 if (do_stop) {
2404 stop_output_stream(out);
2405 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002406 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002408 return 0;
2409}
2410
2411static int out_standby(struct audio_stream *stream)
2412{
2413 struct stream_out *out = (struct stream_out *)stream;
2414
2415 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2416 out->usecase, use_case_table[out->usecase]);
2417
2418 lock_output_stream(out);
2419 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002421 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422 return 0;
2423}
2424
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002425static int out_on_error(struct audio_stream *stream)
2426{
2427 struct stream_out *out = (struct stream_out *)stream;
2428 struct audio_device *adev = out->dev;
2429 bool do_standby = false;
2430
2431 lock_output_stream(out);
2432 if (!out->standby) {
2433 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2434 stop_compressed_output_l(out);
2435 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2436 } else
2437 do_standby = true;
2438 }
2439 pthread_mutex_unlock(&out->lock);
2440
2441 if (do_standby)
2442 return out_standby(&out->stream.common);
2443
2444 return 0;
2445}
2446
Andy Hung7401c7c2016-09-21 12:41:21 -07002447static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448{
Andy Hung7401c7c2016-09-21 12:41:21 -07002449 struct stream_out *out = (struct stream_out *)stream;
2450
2451 // We try to get the lock for consistency,
2452 // but it isn't necessary for these variables.
2453 // If we're not in standby, we may be blocked on a write.
2454 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2455 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2456 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2457
2458 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002459 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002460 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002461
2462 // dump error info
2463 (void)error_log_dump(
2464 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 return 0;
2467}
2468
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002469static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2470{
2471 int ret = 0;
2472 char value[32];
2473 struct compr_gapless_mdata tmp_mdata;
2474
2475 if (!out || !parms) {
2476 return -EINVAL;
2477 }
2478
2479 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2480 if (ret >= 0) {
2481 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2482 } else {
2483 return -EINVAL;
2484 }
2485
2486 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2487 if (ret >= 0) {
2488 tmp_mdata.encoder_padding = atoi(value);
2489 } else {
2490 return -EINVAL;
2491 }
2492
2493 out->gapless_mdata = tmp_mdata;
2494 out->send_new_metadata = 1;
2495 ALOGV("%s new encoder delay %u and padding %u", __func__,
2496 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2497
2498 return 0;
2499}
2500
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002501static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2502{
2503 return out == adev->primary_output || out == adev->voice_tx_output;
2504}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002505
Kevin Rocard1e02c882017-08-09 15:26:07 -07002506static int get_alive_usb_card(struct str_parms* parms) {
2507 int card;
2508 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2509 !audio_extn_usb_alive(card)) {
2510 return card;
2511 }
2512 return -ENODEV;
2513}
2514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2516{
2517 struct stream_out *out = (struct stream_out *)stream;
2518 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002519 struct audio_usecase *usecase;
2520 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 struct str_parms *parms;
2522 char value[32];
2523 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002524 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002525 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002526 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527
Eric Laurent2e140aa2016-06-30 17:14:46 -07002528 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002529 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530 parms = str_parms_create_str(kvpairs);
2531 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2532 if (ret >= 0) {
2533 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002534
Eric Laurenta1478072015-09-21 17:21:52 -07002535 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002536
2537 // The usb driver needs to be closed after usb device disconnection
2538 // otherwise audio is no longer played on the new usb devices.
2539 // By forcing the stream in standby, the usb stack refcount drops to 0
2540 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002541 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002542 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002543 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2544 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2545 out_standby_l(&out->stream.common);
2546 }
2547 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002548 }
2549
Eric Laurent150dbfe2013-02-27 14:31:02 -08002550 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002552 /*
2553 * When HDMI cable is unplugged the music playback is paused and
2554 * the policy manager sends routing=0. But the audioflinger
2555 * continues to write data until standby time (3sec).
2556 * As the HDMI core is turned off, the write gets blocked.
2557 * Avoid this by routing audio to speaker until standby.
2558 */
2559 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2560 val == AUDIO_DEVICE_NONE) {
2561 val = AUDIO_DEVICE_OUT_SPEAKER;
2562 }
2563
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002564 /*
2565 * When A2DP is disconnected the
2566 * music playback is paused and the policy manager sends routing=0
2567 * But the audioflingercontinues to write data until standby time
2568 * (3sec). As BT is turned off, the write gets blocked.
2569 * Avoid this by routing audio to speaker until standby.
2570 */
2571 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2572 (val == AUDIO_DEVICE_NONE) &&
2573 !audio_extn_a2dp_is_ready()) {
2574 val = AUDIO_DEVICE_OUT_SPEAKER;
2575 }
2576
2577 /* To avoid a2dp to sco overlapping / BT device improper state
2578 * check with BT lib about a2dp streaming support before routing
2579 */
2580 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2581 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002582 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002583 //combo usecase just by pass a2dp
2584 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2585 bypass_a2dp = true;
2586 } else {
2587 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2588 /* update device to a2dp and don't route as BT returned error
2589 * However it is still possible a2dp routing called because
2590 * of current active device disconnection (like wired headset)
2591 */
2592 out->devices = val;
2593 pthread_mutex_unlock(&out->lock);
2594 pthread_mutex_unlock(&adev->lock);
2595 status = -ENOSYS;
2596 goto routing_fail;
2597 }
2598 }
2599 }
2600
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002601 audio_devices_t new_dev = val;
2602
2603 // Workaround: If routing to an non existing usb device, fail gracefully
2604 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002605 int card;
2606 if (audio_is_usb_out_device(new_dev) &&
2607 (card = get_alive_usb_card(parms)) >= 0) {
2608
2609 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002610 pthread_mutex_unlock(&adev->lock);
2611 pthread_mutex_unlock(&out->lock);
2612 status = -ENOSYS;
2613 goto routing_fail;
2614 }
2615
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002616 /*
2617 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002618 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002619 * the select_devices(). But how do we undo this?
2620 *
2621 * For example, music playback is active on headset (deep-buffer usecase)
2622 * and if we go to ringtones and select a ringtone, low-latency usecase
2623 * will be started on headset+speaker. As we can't enable headset+speaker
2624 * and headset devices at the same time, select_devices() switches the music
2625 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2626 * So when the ringtone playback is completed, how do we undo the same?
2627 *
2628 * We are relying on the out_set_parameters() call on deep-buffer output,
2629 * once the ringtone playback is ended.
2630 * NOTE: We should not check if the current devices are same as new devices.
2631 * Because select_devices() must be called to switch back the music
2632 * playback to headset.
2633 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002634 if (new_dev != AUDIO_DEVICE_NONE) {
2635 bool same_dev = out->devices == new_dev;
2636 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002637
Eric Laurenta7657192014-10-09 21:09:33 -07002638 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002639 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002640 if (adev->mode == AUDIO_MODE_IN_CALL) {
2641 adev->current_call_output = out;
2642 ret = voice_start_call(adev);
2643 }
2644 } else {
2645 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002646 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002647 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002648 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002649
2650 if (!out->standby) {
2651 if (!same_dev) {
2652 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002653 // inform adm before actual routing to prevent glitches.
2654 if (adev->adm_on_routing_change) {
2655 adev->adm_on_routing_change(adev->adm_data,
2656 out->handle);
2657 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002658 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002659 if (!bypass_a2dp) {
2660 select_devices(adev, out->usecase);
2661 } else {
juyuchen9baad392018-06-05 19:02:10 +08002662 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2663 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2664 else
2665 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002666 select_devices(adev, out->usecase);
2667 out->devices = new_dev;
2668 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002669 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002670
2671 // on device switch force swap, lower functions will make sure
2672 // to check if swap is allowed or not.
2673
2674 if (!same_dev)
2675 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002676
2677 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2678 out->a2dp_compress_mute &&
2679 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2680 pthread_mutex_lock(&out->compr_mute_lock);
2681 out->a2dp_compress_mute = false;
2682 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2683 pthread_mutex_unlock(&out->compr_mute_lock);
2684 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002685 }
2686
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002687 }
2688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002690 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002691
2692 /*handles device and call state changes*/
2693 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002695 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002696
2697 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2698 parse_compress_metadata(out, parms);
2699 }
2700
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002702 ALOGV("%s: exit: code(%d)", __func__, status);
2703 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
Haynes Mathew George569b7482017-05-08 14:44:27 -07002706static bool stream_get_parameter_channels(struct str_parms *query,
2707 struct str_parms *reply,
2708 audio_channel_mask_t *supported_channel_masks) {
2709 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002710 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002712 size_t i, j;
2713
2714 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2715 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 value[0] = '\0';
2717 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002718 while (supported_channel_masks[i] != 0) {
2719 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2720 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 if (!first) {
2722 strcat(value, "|");
2723 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002724 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725 first = false;
2726 break;
2727 }
2728 }
2729 i++;
2730 }
2731 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002732 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002733 return ret >= 0;
2734}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002735
Haynes Mathew George569b7482017-05-08 14:44:27 -07002736static bool stream_get_parameter_formats(struct str_parms *query,
2737 struct str_parms *reply,
2738 audio_format_t *supported_formats) {
2739 int ret = -1;
2740 char value[256];
2741 int i;
2742
2743 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2744 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002745 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002746 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002747 case AUDIO_FORMAT_PCM_16_BIT:
2748 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2749 break;
2750 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2751 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2752 break;
2753 case AUDIO_FORMAT_PCM_32_BIT:
2754 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2755 break;
2756 default:
2757 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002758 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002759 break;
2760 }
2761 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002762 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002763 return ret >= 0;
2764}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002765
Haynes Mathew George569b7482017-05-08 14:44:27 -07002766static bool stream_get_parameter_rates(struct str_parms *query,
2767 struct str_parms *reply,
2768 uint32_t *supported_sample_rates) {
2769
2770 int i;
2771 char value[256];
2772 int ret = -1;
2773 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2774 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002775 value[0] = '\0';
2776 i=0;
2777 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002778 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002779 int avail = sizeof(value) - cursor;
2780 ret = snprintf(value + cursor, avail, "%s%d",
2781 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002782 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002783 if (ret < 0 || ret >= avail) {
2784 // if cursor is at the last element of the array
2785 // overwrite with \0 is duplicate work as
2786 // snprintf already put a \0 in place.
2787 // else
2788 // we had space to write the '|' at value[cursor]
2789 // (which will be overwritten) or no space to fill
2790 // the first element (=> cursor == 0)
2791 value[cursor] = '\0';
2792 break;
2793 }
2794 cursor += ret;
2795 ++i;
2796 }
2797 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2798 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002799 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002800 return ret >= 0;
2801}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002802
Haynes Mathew George569b7482017-05-08 14:44:27 -07002803static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2804{
2805 struct stream_out *out = (struct stream_out *)stream;
2806 struct str_parms *query = str_parms_create_str(keys);
2807 char *str;
2808 struct str_parms *reply = str_parms_create();
2809 bool replied = false;
2810 ALOGV("%s: enter: keys - %s", __func__, keys);
2811
2812 replied |= stream_get_parameter_channels(query, reply,
2813 &out->supported_channel_masks[0]);
2814 replied |= stream_get_parameter_formats(query, reply,
2815 &out->supported_formats[0]);
2816 replied |= stream_get_parameter_rates(query, reply,
2817 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002818 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 str = str_parms_to_str(reply);
2820 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002821 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 }
2823 str_parms_destroy(query);
2824 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002825 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 return str;
2827}
2828
2829static uint32_t out_get_latency(const struct audio_stream_out *stream)
2830{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002831 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002833 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2836 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002837 else if ((out->realtime) ||
2838 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002839 // since the buffer won't be filled up faster than realtime,
2840 // return a smaller number
2841 period_ms = (out->af_period_multiplier * out->config.period_size *
2842 1000) / (out->config.rate);
2843 hw_delay = platform_render_latency(out->usecase)/1000;
2844 return period_ms + hw_delay;
2845 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002847 latency = (out->config.period_count * out->config.period_size * 1000) /
2848 (out->config.rate);
2849
2850 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2851 latency += audio_extn_a2dp_get_encoder_latency();
2852
2853 return latency;
2854}
2855
2856static int set_compr_volume(struct audio_stream_out *stream, float left,
2857 float right)
2858{
2859 struct stream_out *out = (struct stream_out *)stream;
2860 int volume[2];
2861 char mixer_ctl_name[128];
2862 struct audio_device *adev = out->dev;
2863 struct mixer_ctl *ctl;
2864 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2865 PCM_PLAYBACK);
2866
2867 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2868 "Compress Playback %d Volume", pcm_device_id);
2869 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2870 if (!ctl) {
2871 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2872 __func__, mixer_ctl_name);
2873 return -EINVAL;
2874 }
2875 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2876 __func__, mixer_ctl_name, left, right);
2877 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2878 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2879 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2880
2881 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882}
2883
2884static int out_set_volume(struct audio_stream_out *stream, float left,
2885 float right)
2886{
Eric Laurenta9024de2013-04-04 09:19:12 -07002887 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002888 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002890 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002891 /* only take left channel into account: the API is for stereo anyway */
2892 out->muted = (left == 0.0f);
2893 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002895 pthread_mutex_lock(&out->compr_mute_lock);
2896 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2897 if (!out->a2dp_compress_mute)
2898 ret = set_compr_volume(stream, left, right);
2899 out->volume_l = left;
2900 out->volume_r = right;
2901 pthread_mutex_unlock(&out->compr_mute_lock);
2902 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002903 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002904 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2905 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2906 if (!out->standby) {
2907 // if in standby, cached volume will be sent after stream is opened
2908 audio_extn_utils_send_app_type_gain(out->dev,
2909 out->app_type_cfg.app_type,
2910 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002911 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002912 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002913 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002914
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002915 return -ENOSYS;
2916}
2917
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002918// note: this call is safe only if the stream_cb is
2919// removed first in close_output_stream (as is done now).
2920static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2921{
2922 if (!stream || !parms)
2923 return;
2924
2925 struct stream_out *out = (struct stream_out *)stream;
2926 struct audio_device *adev = out->dev;
2927
2928 card_status_t status;
2929 int card;
2930 if (parse_snd_card_status(parms, &card, &status) < 0)
2931 return;
2932
2933 pthread_mutex_lock(&adev->lock);
2934 bool valid_cb = (card == adev->snd_card);
2935 pthread_mutex_unlock(&adev->lock);
2936
2937 if (!valid_cb)
2938 return;
2939
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002940 lock_output_stream(out);
2941 if (out->card_status != status)
2942 out->card_status = status;
2943 pthread_mutex_unlock(&out->lock);
2944
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002945 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2946 use_case_table[out->usecase],
2947 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2948
2949 if (status == CARD_STATUS_OFFLINE)
2950 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002951
2952 return;
2953}
2954
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002955#ifdef NO_AUDIO_OUT
2956static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002957 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002958{
2959 struct stream_out *out = (struct stream_out *)stream;
2960
2961 /* No Output device supported other than BT for playback.
2962 * Sleep for the amount of buffer duration
2963 */
Eric Laurenta1478072015-09-21 17:21:52 -07002964 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002965 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2966 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002967 out_get_sample_rate(&out->stream.common));
2968 pthread_mutex_unlock(&out->lock);
2969 return bytes;
2970}
2971#endif
2972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2974 size_t bytes)
2975{
2976 struct stream_out *out = (struct stream_out *)stream;
2977 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002978 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002979 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980
Eric Laurenta1478072015-09-21 17:21:52 -07002981 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002982 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002983 const size_t frame_size = audio_stream_out_frame_size(stream);
2984 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002985
Eric Laurent0e46adf2016-12-16 12:49:24 -08002986 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2987 error_code = ERROR_CODE_WRITE;
2988 goto exit;
2989 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002990
2991 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2992 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002993 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002994 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2995 ret = -EIO;
2996 goto exit;
2997 }
2998 }
2999 }
3000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003002 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003003 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003005
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003006 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003008 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003009 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010 goto exit;
3011 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003012
vivek mehta40125092017-08-21 18:48:51 -07003013 // after standby always force set last known cal step
3014 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3015 ALOGD("%s: retry previous failed cal level set", __func__);
3016 send_gain_dep_calibration_l();
3017 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003021 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003022 if (out->send_new_metadata) {
3023 ALOGVV("send new gapless metadata");
3024 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3025 out->send_new_metadata = 0;
3026 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003027 unsigned int avail;
3028 struct timespec tstamp;
3029 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3030 /* Do not limit write size if the available frames count is unknown */
3031 if (ret != 0) {
3032 avail = bytes;
3033 }
3034 if (avail == 0) {
3035 ret = 0;
3036 } else {
3037 if (avail > bytes) {
3038 avail = bytes;
3039 }
3040 ret = compress_write(out->compr, buffer, avail);
3041 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3042 __func__, avail, ret);
3043 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003044
Eric Laurent6e895242013-09-05 16:10:57 -07003045 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3047 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003048 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049 compress_start(out->compr);
3050 out->playback_started = 1;
3051 out->offload_state = OFFLOAD_STATE_PLAYING;
3052 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003053 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003054 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003055 } else {
3056 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003057 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003059 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 return ret;
3061 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003062 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003064 size_t bytes_to_write = bytes;
3065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003066 if (out->muted)
3067 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003068 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003069 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003070 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3071 int16_t *src = (int16_t *)buffer;
3072 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003073
Eric Laurentad2dde92017-09-20 18:27:31 -07003074 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3075 out->format != AUDIO_FORMAT_PCM_16_BIT,
3076 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003077
Eric Laurentad2dde92017-09-20 18:27:31 -07003078 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3079 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3080 }
3081 bytes_to_write /= 2;
3082 }
3083 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3084
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003085 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003086 request_out_focus(out, ns);
3087
3088 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3089 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003090 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003091 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003092 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003093
Haynes Mathew George03c40102016-01-29 17:57:48 -08003094 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003095 } else {
3096 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 }
3099
3100exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003101 // For PCM we always consume the buffer and return #bytes regardless of ret.
3102 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003103 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003104 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003105 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003106
Andy Hung7401c7c2016-09-21 12:41:21 -07003107 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003108 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003109 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3110 ALOGE_IF(out->pcm != NULL,
3111 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003112 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003113 // usleep not guaranteed for values over 1 second but we don't limit here.
3114 }
3115 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 pthread_mutex_unlock(&out->lock);
3118
3119 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003120 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003121 if (sleeptime_us != 0)
3122 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 }
3124 return bytes;
3125}
3126
3127static int out_get_render_position(const struct audio_stream_out *stream,
3128 uint32_t *dsp_frames)
3129{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003130 struct stream_out *out = (struct stream_out *)stream;
3131 *dsp_frames = 0;
3132 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003133 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003134 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003135 unsigned long frames = 0;
3136 // TODO: check return value
3137 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3138 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 ALOGVV("%s rendered frames %d sample_rate %d",
3140 __func__, *dsp_frames, out->sample_rate);
3141 }
3142 pthread_mutex_unlock(&out->lock);
3143 return 0;
3144 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003145 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146}
3147
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003148static int out_add_audio_effect(const struct audio_stream *stream __unused,
3149 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150{
3151 return 0;
3152}
3153
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003154static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3155 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156{
3157 return 0;
3158}
3159
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003160static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3161 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003163 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164}
3165
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003166static int out_get_presentation_position(const struct audio_stream_out *stream,
3167 uint64_t *frames, struct timespec *timestamp)
3168{
3169 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003170 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003171 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003172
Eric Laurenta1478072015-09-21 17:21:52 -07003173 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003174
Eric Laurent949a0892013-09-20 09:20:13 -07003175 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3176 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003177 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003178 compress_get_tstamp(out->compr, &dsp_frames,
3179 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003180 // Adjustment accounts for A2DP encoder latency with offload usecases
3181 // Note: Encoder latency is returned in ms.
3182 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3183 unsigned long offset =
3184 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3185 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3186 }
Eric Laurent949a0892013-09-20 09:20:13 -07003187 ALOGVV("%s rendered frames %ld sample_rate %d",
3188 __func__, dsp_frames, out->sample_rate);
3189 *frames = dsp_frames;
3190 ret = 0;
3191 /* this is the best we can do */
3192 clock_gettime(CLOCK_MONOTONIC, timestamp);
3193 }
3194 } else {
3195 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003196 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003197 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3198 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003199 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003200 // This adjustment accounts for buffering after app processor.
3201 // It is based on estimated DSP latency per use case, rather than exact.
3202 signed_frames -=
3203 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3204
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003205 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3206 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3207 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3208 signed_frames -=
3209 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3210 }
3211
Eric Laurent949a0892013-09-20 09:20:13 -07003212 // It would be unusual for this value to be negative, but check just in case ...
3213 if (signed_frames >= 0) {
3214 *frames = signed_frames;
3215 ret = 0;
3216 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003217 }
3218 }
3219 }
3220
3221 pthread_mutex_unlock(&out->lock);
3222
3223 return ret;
3224}
3225
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003226static int out_set_callback(struct audio_stream_out *stream,
3227 stream_callback_t callback, void *cookie)
3228{
3229 struct stream_out *out = (struct stream_out *)stream;
3230
3231 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003232 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003233 out->offload_callback = callback;
3234 out->offload_cookie = cookie;
3235 pthread_mutex_unlock(&out->lock);
3236 return 0;
3237}
3238
3239static int out_pause(struct audio_stream_out* stream)
3240{
3241 struct stream_out *out = (struct stream_out *)stream;
3242 int status = -ENOSYS;
3243 ALOGV("%s", __func__);
3244 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003245 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003246 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3247 status = compress_pause(out->compr);
3248 out->offload_state = OFFLOAD_STATE_PAUSED;
3249 }
3250 pthread_mutex_unlock(&out->lock);
3251 }
3252 return status;
3253}
3254
3255static int out_resume(struct audio_stream_out* stream)
3256{
3257 struct stream_out *out = (struct stream_out *)stream;
3258 int status = -ENOSYS;
3259 ALOGV("%s", __func__);
3260 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3261 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003262 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3264 status = compress_resume(out->compr);
3265 out->offload_state = OFFLOAD_STATE_PLAYING;
3266 }
3267 pthread_mutex_unlock(&out->lock);
3268 }
3269 return status;
3270}
3271
3272static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3273{
3274 struct stream_out *out = (struct stream_out *)stream;
3275 int status = -ENOSYS;
3276 ALOGV("%s", __func__);
3277 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003278 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003279 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3280 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3281 else
3282 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3283 pthread_mutex_unlock(&out->lock);
3284 }
3285 return status;
3286}
3287
3288static int out_flush(struct audio_stream_out* stream)
3289{
3290 struct stream_out *out = (struct stream_out *)stream;
3291 ALOGV("%s", __func__);
3292 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003293 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 stop_compressed_output_l(out);
3295 pthread_mutex_unlock(&out->lock);
3296 return 0;
3297 }
3298 return -ENOSYS;
3299}
3300
Eric Laurent0e46adf2016-12-16 12:49:24 -08003301static int out_stop(const struct audio_stream_out* stream)
3302{
3303 struct stream_out *out = (struct stream_out *)stream;
3304 struct audio_device *adev = out->dev;
3305 int ret = -ENOSYS;
3306
3307 ALOGV("%s", __func__);
3308 pthread_mutex_lock(&adev->lock);
3309 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3310 out->playback_started && out->pcm != NULL) {
3311 pcm_stop(out->pcm);
3312 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003313 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003314 }
3315 pthread_mutex_unlock(&adev->lock);
3316 return ret;
3317}
3318
3319static int out_start(const struct audio_stream_out* stream)
3320{
3321 struct stream_out *out = (struct stream_out *)stream;
3322 struct audio_device *adev = out->dev;
3323 int ret = -ENOSYS;
3324
3325 ALOGV("%s", __func__);
3326 pthread_mutex_lock(&adev->lock);
3327 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3328 !out->playback_started && out->pcm != NULL) {
3329 ret = start_output_stream(out);
3330 if (ret == 0) {
3331 out->playback_started = true;
3332 }
3333 }
3334 pthread_mutex_unlock(&adev->lock);
3335 return ret;
3336}
3337
Phil Burkbc991042017-02-24 08:06:44 -08003338/*
3339 * Modify config->period_count based on min_size_frames
3340 */
3341static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3342{
3343 int periodCountRequested = (min_size_frames + config->period_size - 1)
3344 / config->period_size;
3345 int periodCount = MMAP_PERIOD_COUNT_MIN;
3346
3347 ALOGV("%s original config.period_size = %d config.period_count = %d",
3348 __func__, config->period_size, config->period_count);
3349
3350 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3351 periodCount *= 2;
3352 }
3353 config->period_count = periodCount;
3354
3355 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3356}
3357
Eric Laurent0e46adf2016-12-16 12:49:24 -08003358static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3359 int32_t min_size_frames,
3360 struct audio_mmap_buffer_info *info)
3361{
3362 struct stream_out *out = (struct stream_out *)stream;
3363 struct audio_device *adev = out->dev;
3364 int ret = 0;
3365 unsigned int offset1;
3366 unsigned int frames1;
3367 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003368 uint32_t mmap_size;
3369 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003370
3371 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003372 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003373 pthread_mutex_lock(&adev->lock);
3374
3375 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003376 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003377 ret = -EINVAL;
3378 goto exit;
3379 }
3380 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003381 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003382 ret = -ENOSYS;
3383 goto exit;
3384 }
3385 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3386 if (out->pcm_device_id < 0) {
3387 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3388 __func__, out->pcm_device_id, out->usecase);
3389 ret = -EINVAL;
3390 goto exit;
3391 }
Phil Burkbc991042017-02-24 08:06:44 -08003392
3393 adjust_mmap_period_count(&out->config, min_size_frames);
3394
Eric Laurent0e46adf2016-12-16 12:49:24 -08003395 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3396 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3397 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3398 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3399 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3400 step = "open";
3401 ret = -ENODEV;
3402 goto exit;
3403 }
3404 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3405 if (ret < 0) {
3406 step = "begin";
3407 goto exit;
3408 }
3409 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003410 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003411 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003412 ret = platform_get_mmap_data_fd(adev->platform,
3413 out->pcm_device_id, 0 /*playback*/,
3414 &info->shared_memory_fd,
3415 &mmap_size);
3416 if (ret < 0) {
3417 // Fall back to non exclusive mode
3418 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3419 } else {
3420 if (mmap_size < buffer_size) {
3421 step = "mmap";
3422 goto exit;
3423 }
3424 // FIXME: indicate exclusive mode support by returning a negative buffer size
3425 info->buffer_size_frames *= -1;
3426 }
3427 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003428
3429 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3430 if (ret < 0) {
3431 step = "commit";
3432 goto exit;
3433 }
Phil Burkbc991042017-02-24 08:06:44 -08003434
3435 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003436 ret = 0;
3437
3438 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3439 __func__, info->shared_memory_address, info->buffer_size_frames);
3440
3441exit:
3442 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003443 if (out->pcm == NULL) {
3444 ALOGE("%s: %s - %d", __func__, step, ret);
3445 } else {
3446 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003447 pcm_close(out->pcm);
3448 out->pcm = NULL;
3449 }
3450 }
3451 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003452 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003453 return ret;
3454}
3455
3456static int out_get_mmap_position(const struct audio_stream_out *stream,
3457 struct audio_mmap_position *position)
3458{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003459 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003460 struct stream_out *out = (struct stream_out *)stream;
3461 ALOGVV("%s", __func__);
3462 if (position == NULL) {
3463 return -EINVAL;
3464 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003465 lock_output_stream(out);
3466 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3467 out->pcm == NULL) {
3468 ret = -ENOSYS;
3469 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003470 }
3471
3472 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003473 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003474 if (ret < 0) {
3475 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003476 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003477 }
Andy Hungfc044e12017-03-20 09:24:22 -07003478 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003479exit:
3480 pthread_mutex_unlock(&out->lock);
3481 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003482}
3483
3484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485/** audio_stream_in implementation **/
3486static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3487{
3488 struct stream_in *in = (struct stream_in *)stream;
3489
3490 return in->config.rate;
3491}
3492
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003493static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494{
3495 return -ENOSYS;
3496}
3497
3498static size_t in_get_buffer_size(const struct audio_stream *stream)
3499{
3500 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003501 return in->config.period_size * in->af_period_multiplier *
3502 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503}
3504
3505static uint32_t in_get_channels(const struct audio_stream *stream)
3506{
3507 struct stream_in *in = (struct stream_in *)stream;
3508
3509 return in->channel_mask;
3510}
3511
vivek mehta4ed66e62016-04-15 23:33:34 -07003512static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513{
vivek mehta4ed66e62016-04-15 23:33:34 -07003514 struct stream_in *in = (struct stream_in *)stream;
3515 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516}
3517
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003518static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519{
3520 return -ENOSYS;
3521}
3522
3523static int in_standby(struct audio_stream *stream)
3524{
3525 struct stream_in *in = (struct stream_in *)stream;
3526 struct audio_device *adev = in->dev;
3527 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003528 bool do_stop = true;
3529
Eric Laurent994a6932013-07-17 11:51:42 -07003530 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003531
3532 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003533
3534 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003535 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003536 audio_extn_sound_trigger_stop_lab(in);
3537 in->standby = true;
3538 }
3539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003541 if (adev->adm_deregister_stream)
3542 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3543
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003544 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003546 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003547 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003548 in->capture_started = false;
3549 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003550 if (in->pcm) {
3551 pcm_close(in->pcm);
3552 in->pcm = NULL;
3553 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003554 adev->enable_voicerx = false;
3555 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003556 if (do_stop) {
3557 status = stop_input_stream(in);
3558 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003559 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 }
3561 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003562 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 return status;
3564}
3565
Andy Hungd13f0d32017-06-12 13:58:37 -07003566static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567{
Andy Hungd13f0d32017-06-12 13:58:37 -07003568 struct stream_in *in = (struct stream_in *)stream;
3569
3570 // We try to get the lock for consistency,
3571 // but it isn't necessary for these variables.
3572 // If we're not in standby, we may be blocked on a read.
3573 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3574 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3575 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3576 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3577
3578 if (locked) {
3579 pthread_mutex_unlock(&in->lock);
3580 }
3581
3582 // dump error info
3583 (void)error_log_dump(
3584 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003585 return 0;
3586}
3587
3588static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3589{
3590 struct stream_in *in = (struct stream_in *)stream;
3591 struct audio_device *adev = in->dev;
3592 struct str_parms *parms;
3593 char *str;
3594 char value[32];
3595 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003596 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597
Eric Laurent994a6932013-07-17 11:51:42 -07003598 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599 parms = str_parms_create_str(kvpairs);
3600
3601 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3602
Eric Laurenta1478072015-09-21 17:21:52 -07003603 lock_input_stream(in);
3604
Eric Laurent150dbfe2013-02-27 14:31:02 -08003605 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 if (ret >= 0) {
3607 val = atoi(value);
3608 /* no audio source uses val == 0 */
3609 if ((in->source != val) && (val != 0)) {
3610 in->source = val;
3611 }
3612 }
3613
3614 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 if (ret >= 0) {
3617 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003618 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003619
3620 // Workaround: If routing to an non existing usb device, fail gracefully
3621 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003622 int card;
3623 if (audio_is_usb_in_device(val) &&
3624 (card = get_alive_usb_card(parms)) >= 0) {
3625
3626 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003627 status = -ENOSYS;
3628 } else {
3629
3630 in->device = val;
3631 /* If recording is in progress, change the tx device to new device */
3632 if (!in->standby) {
3633 ALOGV("update input routing change");
3634 // inform adm before actual routing to prevent glitches.
3635 if (adev->adm_on_routing_change) {
3636 adev->adm_on_routing_change(adev->adm_data,
3637 in->capture_handle);
3638 }
3639 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003640 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 }
3643 }
3644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003646 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647
3648 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003649 ALOGV("%s: exit: status(%d)", __func__, status);
3650 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003651}
3652
Haynes Mathew George569b7482017-05-08 14:44:27 -07003653static char* in_get_parameters(const struct audio_stream *stream,
3654 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003656 struct stream_in *in = (struct stream_in *)stream;
3657 struct str_parms *query = str_parms_create_str(keys);
3658 char *str;
3659 struct str_parms *reply = str_parms_create();
3660 bool replied = false;
3661
3662 ALOGV("%s: enter: keys - %s", __func__, keys);
3663 replied |= stream_get_parameter_channels(query, reply,
3664 &in->supported_channel_masks[0]);
3665 replied |= stream_get_parameter_formats(query, reply,
3666 &in->supported_formats[0]);
3667 replied |= stream_get_parameter_rates(query, reply,
3668 &in->supported_sample_rates[0]);
3669 if (replied) {
3670 str = str_parms_to_str(reply);
3671 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003672 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003673 }
3674 str_parms_destroy(query);
3675 str_parms_destroy(reply);
3676 ALOGV("%s: exit: returns - %s", __func__, str);
3677 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678}
3679
Eric Laurent51f3c662018-04-10 18:21:34 -07003680static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681{
Eric Laurent51f3c662018-04-10 18:21:34 -07003682 struct stream_in *in = (struct stream_in *)stream;
3683 char mixer_ctl_name[128];
3684 struct mixer_ctl *ctl;
3685 int ctl_value;
3686
3687 ALOGV("%s: gain %f", __func__, gain);
3688
3689 if (stream == NULL)
3690 return -EINVAL;
3691
3692 /* in_set_gain() only used to silence MMAP capture for now */
3693 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3694 return -ENOSYS;
3695
3696 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3697
3698 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3699 if (!ctl) {
3700 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3701 __func__, mixer_ctl_name);
3702 return -ENOSYS;
3703 }
3704
3705 if (gain < RECORD_GAIN_MIN)
3706 gain = RECORD_GAIN_MIN;
3707 else if (gain > RECORD_GAIN_MAX)
3708 gain = RECORD_GAIN_MAX;
3709 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3710
3711 mixer_ctl_set_value(ctl, 0, ctl_value);
3712 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713}
3714
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003715static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3716{
3717 if (!stream || !parms)
3718 return;
3719
3720 struct stream_in *in = (struct stream_in *)stream;
3721 struct audio_device *adev = in->dev;
3722
3723 card_status_t status;
3724 int card;
3725 if (parse_snd_card_status(parms, &card, &status) < 0)
3726 return;
3727
3728 pthread_mutex_lock(&adev->lock);
3729 bool valid_cb = (card == adev->snd_card);
3730 pthread_mutex_unlock(&adev->lock);
3731
3732 if (!valid_cb)
3733 return;
3734
3735 lock_input_stream(in);
3736 if (in->card_status != status)
3737 in->card_status = status;
3738 pthread_mutex_unlock(&in->lock);
3739
3740 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3741 use_case_table[in->usecase],
3742 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3743
3744 // a better solution would be to report error back to AF and let
3745 // it put the stream to standby
3746 if (status == CARD_STATUS_OFFLINE)
3747 in_standby(&in->stream.common);
3748
3749 return;
3750}
3751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3753 size_t bytes)
3754{
3755 struct stream_in *in = (struct stream_in *)stream;
3756 struct audio_device *adev = in->dev;
3757 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003758 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003759 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760
Eric Laurenta1478072015-09-21 17:21:52 -07003761 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003762 const size_t frame_size = audio_stream_in_frame_size(stream);
3763 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003764
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003765 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003766 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003767 /* Read from sound trigger HAL */
3768 audio_extn_sound_trigger_read(in, buffer, bytes);
3769 pthread_mutex_unlock(&in->lock);
3770 return bytes;
3771 }
3772
Eric Laurent0e46adf2016-12-16 12:49:24 -08003773 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3774 ret = -ENOSYS;
3775 goto exit;
3776 }
3777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003779 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003781 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783 goto exit;
3784 }
3785 in->standby = 0;
3786 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787
Andy Hungd13f0d32017-06-12 13:58:37 -07003788 // errors that occur here are read errors.
3789 error_code = ERROR_CODE_READ;
3790
Haynes Mathew George03c40102016-01-29 17:57:48 -08003791 //what's the duration requested by the client?
3792 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3793 in->config.rate;
3794 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003795
Haynes Mathew George03c40102016-01-29 17:57:48 -08003796 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003798 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003799 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003800 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003801 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003802 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003803 if (ret < 0) {
3804 ALOGE("Failed to read w/err %s", strerror(errno));
3805 ret = -errno;
3806 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003807 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3808 if (bytes % 4 == 0) {
3809 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3810 int_buf_stream = buffer;
3811 for (size_t itt=0; itt < bytes/4 ; itt++) {
3812 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003813 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003814 } else {
3815 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3816 ret = -EINVAL;
3817 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003818 }
3819 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003820 }
3821
Haynes Mathew George03c40102016-01-29 17:57:48 -08003822 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 /*
3825 * Instead of writing zeroes here, we could trust the hardware
3826 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003827 * No need to acquire adev->lock to read mic_muted here as we don't change its state.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003829 if (ret == 0 && adev->mic_muted &&
3830 !voice_is_in_call_rec_stream(in) &&
3831 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003833 in->frames_muted += frames;
3834 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835
3836exit:
3837 pthread_mutex_unlock(&in->lock);
3838
3839 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003840 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 in_standby(&in->stream.common);
3842 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003843 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003844 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003845 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003846 }
3847 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003848 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 }
3850 return bytes;
3851}
3852
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003853static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854{
3855 return 0;
3856}
3857
Andy Hung6ebe5962016-01-15 17:46:57 -08003858static int in_get_capture_position(const struct audio_stream_in *stream,
3859 int64_t *frames, int64_t *time)
3860{
3861 if (stream == NULL || frames == NULL || time == NULL) {
3862 return -EINVAL;
3863 }
3864 struct stream_in *in = (struct stream_in *)stream;
3865 int ret = -ENOSYS;
3866
3867 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003868 // note: ST sessions do not close the alsa pcm driver synchronously
3869 // on standby. Therefore, we may return an error even though the
3870 // pcm stream is still opened.
3871 if (in->standby) {
3872 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3873 "%s stream in standby but pcm not NULL for non ST session", __func__);
3874 goto exit;
3875 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003876 if (in->pcm) {
3877 struct timespec timestamp;
3878 unsigned int avail;
3879 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3880 *frames = in->frames_read + avail;
3881 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3882 ret = 0;
3883 }
3884 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003885exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003886 pthread_mutex_unlock(&in->lock);
3887 return ret;
3888}
3889
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003890static int add_remove_audio_effect(const struct audio_stream *stream,
3891 effect_handle_t effect,
3892 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003894 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003895 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003896 int status = 0;
3897 effect_descriptor_t desc;
3898
3899 status = (*effect)->get_descriptor(effect, &desc);
3900 if (status != 0)
3901 return status;
3902
Eric Laurenta1478072015-09-21 17:21:52 -07003903 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003904 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003905 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003906 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003907 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003908 in->enable_aec != enable &&
3909 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3910 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003911 if (!enable)
3912 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003913 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3914 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3915 adev->enable_voicerx = enable;
3916 struct audio_usecase *usecase;
3917 struct listnode *node;
3918 list_for_each(node, &adev->usecase_list) {
3919 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003920 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003921 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003922 }
3923 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003924 if (!in->standby)
3925 select_devices(in->dev, in->usecase);
3926 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003927 if (in->enable_ns != enable &&
3928 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3929 in->enable_ns = enable;
3930 if (!in->standby)
3931 select_devices(in->dev, in->usecase);
3932 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003933 pthread_mutex_unlock(&in->dev->lock);
3934 pthread_mutex_unlock(&in->lock);
3935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 return 0;
3937}
3938
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003939static int in_add_audio_effect(const struct audio_stream *stream,
3940 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941{
Eric Laurent994a6932013-07-17 11:51:42 -07003942 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003943 return add_remove_audio_effect(stream, effect, true);
3944}
3945
3946static int in_remove_audio_effect(const struct audio_stream *stream,
3947 effect_handle_t effect)
3948{
Eric Laurent994a6932013-07-17 11:51:42 -07003949 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003950 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951}
3952
Eric Laurent0e46adf2016-12-16 12:49:24 -08003953static int in_stop(const struct audio_stream_in* stream)
3954{
3955 struct stream_in *in = (struct stream_in *)stream;
3956 struct audio_device *adev = in->dev;
3957
3958 int ret = -ENOSYS;
3959 ALOGV("%s", __func__);
3960 pthread_mutex_lock(&adev->lock);
3961 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3962 in->capture_started && in->pcm != NULL) {
3963 pcm_stop(in->pcm);
3964 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003965 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003966 }
3967 pthread_mutex_unlock(&adev->lock);
3968 return ret;
3969}
3970
3971static int in_start(const struct audio_stream_in* stream)
3972{
3973 struct stream_in *in = (struct stream_in *)stream;
3974 struct audio_device *adev = in->dev;
3975 int ret = -ENOSYS;
3976
3977 ALOGV("%s in %p", __func__, in);
3978 pthread_mutex_lock(&adev->lock);
3979 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3980 !in->capture_started && in->pcm != NULL) {
3981 if (!in->capture_started) {
3982 ret = start_input_stream(in);
3983 if (ret == 0) {
3984 in->capture_started = true;
3985 }
3986 }
3987 }
3988 pthread_mutex_unlock(&adev->lock);
3989 return ret;
3990}
3991
3992static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3993 int32_t min_size_frames,
3994 struct audio_mmap_buffer_info *info)
3995{
3996 struct stream_in *in = (struct stream_in *)stream;
3997 struct audio_device *adev = in->dev;
3998 int ret = 0;
3999 unsigned int offset1;
4000 unsigned int frames1;
4001 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004002 uint32_t mmap_size;
4003 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004004
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004005 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004006 pthread_mutex_lock(&adev->lock);
4007 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004008
Eric Laurent0e46adf2016-12-16 12:49:24 -08004009 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004010 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004011 ret = -EINVAL;
4012 goto exit;
4013 }
4014 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004015 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004016 ALOGV("%s in %p", __func__, in);
4017 ret = -ENOSYS;
4018 goto exit;
4019 }
4020 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4021 if (in->pcm_device_id < 0) {
4022 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4023 __func__, in->pcm_device_id, in->usecase);
4024 ret = -EINVAL;
4025 goto exit;
4026 }
Phil Burkbc991042017-02-24 08:06:44 -08004027
4028 adjust_mmap_period_count(&in->config, min_size_frames);
4029
Eric Laurent0e46adf2016-12-16 12:49:24 -08004030 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4031 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4032 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4033 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4034 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4035 step = "open";
4036 ret = -ENODEV;
4037 goto exit;
4038 }
4039
4040 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4041 if (ret < 0) {
4042 step = "begin";
4043 goto exit;
4044 }
4045 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004046 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004047 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004048 ret = platform_get_mmap_data_fd(adev->platform,
4049 in->pcm_device_id, 1 /*capture*/,
4050 &info->shared_memory_fd,
4051 &mmap_size);
4052 if (ret < 0) {
4053 // Fall back to non exclusive mode
4054 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4055 } else {
4056 if (mmap_size < buffer_size) {
4057 step = "mmap";
4058 goto exit;
4059 }
4060 // FIXME: indicate exclusive mode support by returning a negative buffer size
4061 info->buffer_size_frames *= -1;
4062 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004063
Haynes Mathew George96483a22017-03-28 14:52:47 -07004064 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004065
4066 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4067 if (ret < 0) {
4068 step = "commit";
4069 goto exit;
4070 }
4071
Phil Burkbc991042017-02-24 08:06:44 -08004072 in->standby = false;
4073 ret = 0;
4074
Eric Laurent0e46adf2016-12-16 12:49:24 -08004075 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4076 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004077
4078exit:
4079 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004080 if (in->pcm == NULL) {
4081 ALOGE("%s: %s - %d", __func__, step, ret);
4082 } else {
4083 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004084 pcm_close(in->pcm);
4085 in->pcm = NULL;
4086 }
4087 }
4088 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004089 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004090 return ret;
4091}
4092
4093static int in_get_mmap_position(const struct audio_stream_in *stream,
4094 struct audio_mmap_position *position)
4095{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004096 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004097 struct stream_in *in = (struct stream_in *)stream;
4098 ALOGVV("%s", __func__);
4099 if (position == NULL) {
4100 return -EINVAL;
4101 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004102 lock_input_stream(in);
4103 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4104 in->pcm == NULL) {
4105 ret = -ENOSYS;
4106 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004107 }
4108 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004109 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004110 if (ret < 0) {
4111 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004112 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004113 }
Andy Hungfc044e12017-03-20 09:24:22 -07004114 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004115exit:
4116 pthread_mutex_unlock(&in->lock);
4117 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004118}
4119
jiabin8962a4d2018-03-19 18:21:24 -07004120static int in_get_active_microphones(const struct audio_stream_in *stream,
4121 struct audio_microphone_characteristic_t *mic_array,
4122 size_t *mic_count) {
4123 struct stream_in *in = (struct stream_in *)stream;
4124 struct audio_device *adev = in->dev;
4125 ALOGVV("%s", __func__);
4126
4127 lock_input_stream(in);
4128 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004129 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004130 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004131 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004132 pthread_mutex_unlock(&adev->lock);
4133 pthread_mutex_unlock(&in->lock);
4134
4135 return ret;
4136}
4137
4138static int adev_get_microphones(const struct audio_hw_device *dev,
4139 struct audio_microphone_characteristic_t *mic_array,
4140 size_t *mic_count) {
4141 struct audio_device *adev = (struct audio_device *)dev;
4142 ALOGVV("%s", __func__);
4143
4144 pthread_mutex_lock(&adev->lock);
4145 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4146 pthread_mutex_unlock(&adev->lock);
4147
4148 return ret;
4149}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151static int adev_open_output_stream(struct audio_hw_device *dev,
4152 audio_io_handle_t handle,
4153 audio_devices_t devices,
4154 audio_output_flags_t flags,
4155 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004156 struct audio_stream_out **stream_out,
4157 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158{
4159 struct audio_device *adev = (struct audio_device *)dev;
4160 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004161 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004162 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4163 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4164 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165
Andy Hungd9653bd2017-08-01 19:31:39 -07004166 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4167 return -ENOSYS;
4168 }
4169
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004170 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4171 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 *stream_out = NULL;
4173 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4174
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004175 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 if (devices == AUDIO_DEVICE_NONE)
4178 devices = AUDIO_DEVICE_OUT_SPEAKER;
4179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180 out->flags = flags;
4181 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004182 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004183 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004184 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185
4186 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004187 if ((is_hdmi || is_usb_dev) &&
4188 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4189 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4190 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004191 audio_format_t req_format = config->format;
4192 audio_channel_mask_t req_channel_mask = config->channel_mask;
4193 uint32_t req_sample_rate = config->sample_rate;
4194
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004195 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004196 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004197 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004198 if (config->sample_rate == 0)
4199 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004200 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004201 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4202 if (config->format == AUDIO_FORMAT_DEFAULT)
4203 config->format = AUDIO_FORMAT_PCM_16_BIT;
4204 } else if (is_usb_dev) {
4205 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4206 &config->format,
4207 &out->supported_formats[0],
4208 MAX_SUPPORTED_FORMATS,
4209 &config->channel_mask,
4210 &out->supported_channel_masks[0],
4211 MAX_SUPPORTED_CHANNEL_MASKS,
4212 &config->sample_rate,
4213 &out->supported_sample_rates[0],
4214 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004215 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004216 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004217 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004218 if (ret != 0) {
4219 // For MMAP NO IRQ, allow conversions in ADSP
4220 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4221 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004222
Eric Laurentab805ee2018-03-30 12:20:38 -07004223 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4224 config->sample_rate = req_sample_rate;
4225 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4226 config->channel_mask = req_channel_mask;
4227 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4228 config->format = req_format;
4229 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004230
Haynes Mathew George569b7482017-05-08 14:44:27 -07004231 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004232 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004233 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004234 if (is_hdmi) {
4235 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4236 out->config = pcm_config_hdmi_multi;
4237 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4238 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4239 out->config = pcm_config_mmap_playback;
4240 out->stream.start = out_start;
4241 out->stream.stop = out_stop;
4242 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4243 out->stream.get_mmap_position = out_get_mmap_position;
4244 } else {
4245 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4246 out->config = pcm_config_hifi;
4247 }
4248
4249 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004250 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004251 if (is_hdmi) {
4252 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4253 audio_bytes_per_sample(out->format));
4254 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004255 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004256 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004257 pthread_mutex_lock(&adev->lock);
4258 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4259 pthread_mutex_unlock(&adev->lock);
4260
4261 // reject offload during card offline to allow
4262 // fallback to s/w paths
4263 if (offline) {
4264 ret = -ENODEV;
4265 goto error_open;
4266 }
4267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004268 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4269 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4270 ALOGE("%s: Unsupported Offload information", __func__);
4271 ret = -EINVAL;
4272 goto error_open;
4273 }
4274 if (!is_supported_format(config->offload_info.format)) {
4275 ALOGE("%s: Unsupported audio format", __func__);
4276 ret = -EINVAL;
4277 goto error_open;
4278 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004279 out->sample_rate = config->offload_info.sample_rate;
4280 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4281 out->channel_mask = config->offload_info.channel_mask;
4282 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4283 out->channel_mask = config->channel_mask;
4284 else
4285 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4286
4287 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004288
4289 out->compr_config.codec = (struct snd_codec *)
4290 calloc(1, sizeof(struct snd_codec));
4291
4292 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004293
4294 out->stream.set_callback = out_set_callback;
4295 out->stream.pause = out_pause;
4296 out->stream.resume = out_resume;
4297 out->stream.drain = out_drain;
4298 out->stream.flush = out_flush;
4299
4300 out->compr_config.codec->id =
4301 get_snd_codec_id(config->offload_info.format);
4302 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4303 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004304 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004305 out->compr_config.codec->bit_rate =
4306 config->offload_info.bit_rate;
4307 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004308 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004309 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4310
4311 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4312 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004313
4314 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004315 create_offload_callback_thread(out);
4316 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4317 __func__, config->offload_info.version,
4318 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004319 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4320 switch (config->sample_rate) {
4321 case 0:
4322 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4323 break;
4324 case 8000:
4325 case 16000:
4326 case 48000:
4327 out->sample_rate = config->sample_rate;
4328 break;
4329 default:
4330 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4331 config->sample_rate);
4332 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4333 ret = -EINVAL;
4334 goto error_open;
4335 }
4336 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4337 switch (config->channel_mask) {
4338 case AUDIO_CHANNEL_NONE:
4339 case AUDIO_CHANNEL_OUT_STEREO:
4340 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4341 break;
4342 default:
4343 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4344 config->channel_mask);
4345 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4346 ret = -EINVAL;
4347 goto error_open;
4348 }
4349 switch (config->format) {
4350 case AUDIO_FORMAT_DEFAULT:
4351 case AUDIO_FORMAT_PCM_16_BIT:
4352 out->format = AUDIO_FORMAT_PCM_16_BIT;
4353 break;
4354 default:
4355 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4356 config->format);
4357 config->format = AUDIO_FORMAT_PCM_16_BIT;
4358 ret = -EINVAL;
4359 goto error_open;
4360 }
4361
4362 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004363 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004364 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004365 case 0:
4366 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4367 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004368 case 8000:
4369 case 16000:
4370 case 48000:
4371 out->sample_rate = config->sample_rate;
4372 break;
4373 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004374 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4375 config->sample_rate);
4376 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4377 ret = -EINVAL;
4378 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004379 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004380 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4381 switch (config->channel_mask) {
4382 case AUDIO_CHANNEL_NONE:
4383 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4384 break;
4385 case AUDIO_CHANNEL_OUT_STEREO:
4386 out->channel_mask = config->channel_mask;
4387 break;
4388 default:
4389 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4390 config->channel_mask);
4391 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4392 ret = -EINVAL;
4393 break;
4394 }
4395 switch (config->format) {
4396 case AUDIO_FORMAT_DEFAULT:
4397 out->format = AUDIO_FORMAT_PCM_16_BIT;
4398 break;
4399 case AUDIO_FORMAT_PCM_16_BIT:
4400 out->format = config->format;
4401 break;
4402 default:
4403 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4404 config->format);
4405 config->format = AUDIO_FORMAT_PCM_16_BIT;
4406 ret = -EINVAL;
4407 break;
4408 }
4409 if (ret != 0)
4410 goto error_open;
4411
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004412 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4413 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004414 out->config.rate = out->sample_rate;
4415 out->config.channels =
4416 audio_channel_count_from_out_mask(out->channel_mask);
4417 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004418 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004419 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4420 switch (config->sample_rate) {
4421 case 0:
4422 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4423 break;
4424 case 8000:
4425 case 16000:
4426 case 32000:
4427 case 48000:
4428 out->sample_rate = config->sample_rate;
4429 break;
4430 default:
4431 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4432 config->sample_rate);
4433 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4434 ret = -EINVAL;
4435 break;
4436 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004437 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004438 switch (config->channel_mask) {
4439 case AUDIO_CHANNEL_NONE:
4440 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4441 break;
4442 case AUDIO_CHANNEL_OUT_STEREO:
4443 out->channel_mask = config->channel_mask;
4444 break;
4445 default:
4446 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4447 config->channel_mask);
4448 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4449 ret = -EINVAL;
4450 break;
4451 }
4452 switch (config->format) {
4453 case AUDIO_FORMAT_DEFAULT:
4454 out->format = AUDIO_FORMAT_PCM_16_BIT;
4455 break;
4456 case AUDIO_FORMAT_PCM_16_BIT:
4457 out->format = config->format;
4458 break;
4459 default:
4460 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4461 config->format);
4462 config->format = AUDIO_FORMAT_PCM_16_BIT;
4463 ret = -EINVAL;
4464 break;
4465 }
4466 if (ret != 0)
4467 goto error_open;
4468
vivek mehtaa68fea62017-06-08 19:04:02 -07004469 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004470 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4471 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004472 out->config.rate = out->sample_rate;
4473 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004474 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004475 out->sample_rate,
4476 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004477 out->config.channels,
4478 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004479 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004480 out->config.period_size = buffer_size / frame_size;
4481 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4482 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004484 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004485 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4486 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004487 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004488 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4489 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004490 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004491 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004492 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004493 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004494 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004495 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4496 out->config = pcm_config_mmap_playback;
4497 out->stream.start = out_start;
4498 out->stream.stop = out_stop;
4499 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4500 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004501 } else {
4502 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4503 out->config = pcm_config_low_latency;
4504 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004505
4506 if (config->sample_rate == 0) {
4507 out->sample_rate = out->config.rate;
4508 } else {
4509 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004510 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004511 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4512 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4513 } else {
4514 out->channel_mask = config->channel_mask;
4515 }
4516 if (config->format == AUDIO_FORMAT_DEFAULT)
4517 out->format = audio_format_from_pcm_format(out->config.format);
4518 else if (!audio_is_linear_pcm(config->format)) {
4519 config->format = AUDIO_FORMAT_PCM_16_BIT;
4520 ret = -EINVAL;
4521 goto error_open;
4522 } else {
4523 out->format = config->format;
4524 }
4525
4526 out->config.rate = out->sample_rate;
4527 out->config.channels =
4528 audio_channel_count_from_out_mask(out->channel_mask);
4529 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4530 out->config.format = pcm_format_from_audio_format(out->format);
4531 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004533
4534 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4535 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004536 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004537 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4538 __func__, config->sample_rate, config->format, config->channel_mask);
4539 config->sample_rate = out->sample_rate;
4540 config->format = out->format;
4541 config->channel_mask = out->channel_mask;
4542 ret = -EINVAL;
4543 goto error_open;
4544 }
4545
Andy Hung6fcba9c2014-03-18 11:53:32 -07004546 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4547 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004549 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004550 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004551 adev->primary_output = out;
4552 else {
4553 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004554 ret = -EEXIST;
4555 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004556 }
4557 }
4558
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559 /* Check if this usecase is already existing */
4560 pthread_mutex_lock(&adev->lock);
4561 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4562 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004564 ret = -EEXIST;
4565 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566 }
4567 pthread_mutex_unlock(&adev->lock);
4568
4569 out->stream.common.get_sample_rate = out_get_sample_rate;
4570 out->stream.common.set_sample_rate = out_set_sample_rate;
4571 out->stream.common.get_buffer_size = out_get_buffer_size;
4572 out->stream.common.get_channels = out_get_channels;
4573 out->stream.common.get_format = out_get_format;
4574 out->stream.common.set_format = out_set_format;
4575 out->stream.common.standby = out_standby;
4576 out->stream.common.dump = out_dump;
4577 out->stream.common.set_parameters = out_set_parameters;
4578 out->stream.common.get_parameters = out_get_parameters;
4579 out->stream.common.add_audio_effect = out_add_audio_effect;
4580 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4581 out->stream.get_latency = out_get_latency;
4582 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004583#ifdef NO_AUDIO_OUT
4584 out->stream.write = out_write_for_no_output;
4585#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004587#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 out->stream.get_render_position = out_get_render_position;
4589 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004590 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591
Eric Laurent0e46adf2016-12-16 12:49:24 -08004592 if (out->realtime)
4593 out->af_period_multiplier = af_period_multiplier;
4594 else
4595 out->af_period_multiplier = 1;
4596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004598 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004599 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004600
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004601 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004602 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004603 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 config->format = out->stream.common.get_format(&out->stream.common);
4606 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4607 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4608
Kevin Rocarda325aa22018-04-03 09:15:52 -07004609 register_format(out->format, out->supported_formats);
4610 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4611 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4612
Andy Hunga452b0a2017-03-15 14:51:15 -07004613 out->error_log = error_log_create(
4614 ERROR_LOG_ENTRIES,
4615 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4616
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004617 /*
4618 By locking output stream before registering, we allow the callback
4619 to update stream's state only after stream's initial state is set to
4620 adev state.
4621 */
4622 lock_output_stream(out);
4623 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4624 pthread_mutex_lock(&adev->lock);
4625 out->card_status = adev->card_status;
4626 pthread_mutex_unlock(&adev->lock);
4627 pthread_mutex_unlock(&out->lock);
4628
vivek mehta4a824772017-06-08 19:05:49 -07004629 stream_app_type_cfg_init(&out->app_type_cfg);
4630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004632
Eric Laurent994a6932013-07-17 11:51:42 -07004633 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004635
4636error_open:
4637 free(out);
4638 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004639 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004640 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641}
4642
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004643static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 struct audio_stream_out *stream)
4645{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004646 struct stream_out *out = (struct stream_out *)stream;
4647 struct audio_device *adev = out->dev;
4648
Eric Laurent994a6932013-07-17 11:51:42 -07004649 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004650
4651 // must deregister from sndmonitor first to prevent races
4652 // between the callback and close_stream
4653 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004655 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4656 destroy_offload_callback_thread(out);
4657
4658 if (out->compr_config.codec != NULL)
4659 free(out->compr_config.codec);
4660 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004661
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004662 out->a2dp_compress_mute = false;
4663
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004664 if (adev->voice_tx_output == out)
4665 adev->voice_tx_output = NULL;
4666
Andy Hunga452b0a2017-03-15 14:51:15 -07004667 error_log_destroy(out->error_log);
4668 out->error_log = NULL;
4669
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004670 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004671 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004672 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004673 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004674 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004675}
4676
4677static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4678{
4679 struct audio_device *adev = (struct audio_device *)dev;
4680 struct str_parms *parms;
4681 char *str;
4682 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004683 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004685 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004686 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687
Joe Onorato188b6222016-03-01 11:02:27 -08004688 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004689
4690 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691
4692 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004693 status = voice_set_parameters(adev, parms);
4694 if (status != 0) {
4695 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696 }
4697
4698 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4699 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004700 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4702 adev->bluetooth_nrec = true;
4703 else
4704 adev->bluetooth_nrec = false;
4705 }
4706
4707 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4708 if (ret >= 0) {
4709 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4710 adev->screen_off = false;
4711 else
4712 adev->screen_off = true;
4713 }
4714
jasmine cha270b7762018-03-30 15:41:33 +08004715#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004716 ret = str_parms_get_int(parms, "rotation", &val);
4717 if (ret >= 0) {
4718 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004719 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004720 // FIXME: note that the code below assumes that the speakers are in the correct placement
4721 // relative to the user when the device is rotated 90deg from its default rotation. This
4722 // assumption is device-specific, not platform-specific like this code.
4723 case 270:
4724 reverse_speakers = true;
4725 break;
4726 case 0:
4727 case 90:
4728 case 180:
4729 break;
4730 default:
4731 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004732 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004733 }
Eric Laurent03f09432014-03-25 18:09:11 -07004734 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004735 // check and set swap
4736 // - check if orientation changed and speaker active
4737 // - set rotation and cache the rotation value
4738 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004739 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004740 }
jasmine cha270b7762018-03-30 15:41:33 +08004741#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004742
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004743 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4744 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004745 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004746 }
4747
David Linee3fe402017-03-13 10:00:42 -07004748 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4749 if (ret >= 0) {
4750 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004751 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004752 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4753 if (ret >= 0) {
4754 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004755 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004756 }
Eric Laurent99dab492017-06-17 15:19:08 -07004757 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004758 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4759 if (ret >= 0) {
4760 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004761 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004762 }
4763 }
4764 }
4765
4766 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4767 if (ret >= 0) {
4768 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004769 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004770 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4771 if (ret >= 0) {
4772 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004773 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004774 }
Eric Laurent99dab492017-06-17 15:19:08 -07004775 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004776 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4777 if (ret >= 0) {
4778 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004779 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004780 }
4781 }
4782 }
4783
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004784 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004785 audio_extn_ma_set_parameters(adev, parms);
4786
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004787 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4788 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004789 struct audio_usecase *usecase;
4790 struct listnode *node;
4791 list_for_each(node, &adev->usecase_list) {
4792 usecase = node_to_item(node, struct audio_usecase, list);
4793 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004794 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004795 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4796
4797 pthread_mutex_unlock(&adev->lock);
4798 lock_output_stream(usecase->stream.out);
4799 pthread_mutex_lock(&adev->lock);
4800 audio_extn_a2dp_set_handoff_mode(true);
4801 // force device switch to reconfigure encoder
4802 select_devices(adev, usecase->id);
4803 audio_extn_a2dp_set_handoff_mode(false);
4804 pthread_mutex_unlock(&usecase->stream.out->lock);
4805 break;
4806 }
4807 }
4808 }
4809
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004810done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004811 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004812 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004813 ALOGV("%s: exit with code(%d)", __func__, status);
4814 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004815}
4816
4817static char* adev_get_parameters(const struct audio_hw_device *dev,
4818 const char *keys)
4819{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004820 struct audio_device *adev = (struct audio_device *)dev;
4821 struct str_parms *reply = str_parms_create();
4822 struct str_parms *query = str_parms_create_str(keys);
4823 char *str;
4824
4825 pthread_mutex_lock(&adev->lock);
4826
4827 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004828 audio_extn_a2dp_get_parameters(query, reply);
4829
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004830 str = str_parms_to_str(reply);
4831 str_parms_destroy(query);
4832 str_parms_destroy(reply);
4833
4834 pthread_mutex_unlock(&adev->lock);
4835 ALOGV("%s: exit: returns - %s", __func__, str);
4836 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004837}
4838
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004839static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840{
4841 return 0;
4842}
4843
Haynes Mathew George5191a852013-09-11 14:19:36 -07004844static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4845{
4846 int ret;
4847 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004848
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004849 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4850
Haynes Mathew George5191a852013-09-11 14:19:36 -07004851 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004852 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004853 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004854
Haynes Mathew George5191a852013-09-11 14:19:36 -07004855 return ret;
4856}
4857
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004858static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859{
4860 return -ENOSYS;
4861}
4862
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004863static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4864 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865{
4866 return -ENOSYS;
4867}
4868
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004869static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004870{
4871 return -ENOSYS;
4872}
4873
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004874static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875{
4876 return -ENOSYS;
4877}
4878
4879static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4880{
4881 struct audio_device *adev = (struct audio_device *)dev;
4882
4883 pthread_mutex_lock(&adev->lock);
4884 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004885 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004887 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4888 voice_is_in_call(adev)) {
4889 voice_stop_call(adev);
4890 adev->current_call_output = NULL;
4891 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004892 }
4893 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004894
4895 audio_extn_extspk_set_mode(adev->extspk, mode);
4896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897 return 0;
4898}
4899
4900static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4901{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004902 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004904
Eric Laurent2bafff12016-03-17 12:17:23 -07004905 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004906 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004907 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4908 ret = audio_extn_hfp_set_mic_mute(adev, state);
4909 } else {
4910 ret = voice_set_mic_mute(adev, state);
4911 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004912 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004913 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004914
4915 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004916}
4917
4918static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4919{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004920 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921 return 0;
4922}
4923
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004924static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925 const struct audio_config *config)
4926{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004927 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928
Eric Laurent74b55762017-07-09 17:04:53 -07004929 /* Don't know if USB HIFI in this context so use true to be conservative */
4930 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4931 true /*is_usb_hifi */) != 0)
4932 return 0;
4933
vivek mehtaa68fea62017-06-08 19:04:02 -07004934 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4935 config->sample_rate, config->format,
4936 channel_count,
4937 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938}
4939
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004940static bool adev_input_allow_hifi_record(struct audio_device *adev,
4941 audio_devices_t devices,
4942 audio_input_flags_t flags,
4943 audio_source_t source) {
4944 const bool allowed = true;
4945
4946 if (!audio_is_usb_in_device(devices))
4947 return !allowed;
4948
4949 switch (flags) {
4950 case AUDIO_INPUT_FLAG_NONE:
4951 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4952 break;
4953 default:
4954 return !allowed;
4955 }
4956
4957 switch (source) {
4958 case AUDIO_SOURCE_DEFAULT:
4959 case AUDIO_SOURCE_MIC:
4960 case AUDIO_SOURCE_UNPROCESSED:
4961 break;
4962 default:
4963 return !allowed;
4964 }
4965
4966 switch (adev->mode) {
4967 case 0:
4968 break;
4969 default:
4970 return !allowed;
4971 }
4972
4973 return allowed;
4974}
4975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004977 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978 audio_devices_t devices,
4979 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004980 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004981 audio_input_flags_t flags,
4982 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004983 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984{
4985 struct audio_device *adev = (struct audio_device *)dev;
4986 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004987 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004988 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004989 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004990 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004991 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4992 devices,
4993 flags,
4994 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004995 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004996 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004997
Andy Hungd9653bd2017-08-01 19:31:39 -07004998 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4999 return -ENOSYS;
5000 }
5001
Eric Laurent74b55762017-07-09 17:04:53 -07005002 if (!(is_usb_dev && may_use_hifi_record)) {
5003 if (config->sample_rate == 0)
5004 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5005 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5006 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5007 if (config->format == AUDIO_FORMAT_DEFAULT)
5008 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005009
Eric Laurent74b55762017-07-09 17:04:53 -07005010 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5011
5012 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5013 return -EINVAL;
5014 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005016 if (audio_extn_tfa_98xx_is_supported() &&
5017 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005018 return -EINVAL;
5019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005020 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5021
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005022 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005023 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005025 in->stream.common.get_sample_rate = in_get_sample_rate;
5026 in->stream.common.set_sample_rate = in_set_sample_rate;
5027 in->stream.common.get_buffer_size = in_get_buffer_size;
5028 in->stream.common.get_channels = in_get_channels;
5029 in->stream.common.get_format = in_get_format;
5030 in->stream.common.set_format = in_set_format;
5031 in->stream.common.standby = in_standby;
5032 in->stream.common.dump = in_dump;
5033 in->stream.common.set_parameters = in_set_parameters;
5034 in->stream.common.get_parameters = in_get_parameters;
5035 in->stream.common.add_audio_effect = in_add_audio_effect;
5036 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5037 in->stream.set_gain = in_set_gain;
5038 in->stream.read = in_read;
5039 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005040 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005041 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005042
5043 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005044 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005045 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005046 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005047 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005048 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005049
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005050 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5051 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5052 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5053 /* Force channel config requested to mono if incall
5054 record is being requested for only uplink/downlink */
5055 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5056 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5057 ret = -EINVAL;
5058 goto err_open;
5059 }
5060 }
5061
Haynes Mathew George569b7482017-05-08 14:44:27 -07005062 if (is_usb_dev && may_use_hifi_record) {
5063 /* HiFi record selects an appropriate format, channel, rate combo
5064 depending on sink capabilities*/
5065 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5066 &config->format,
5067 &in->supported_formats[0],
5068 MAX_SUPPORTED_FORMATS,
5069 &config->channel_mask,
5070 &in->supported_channel_masks[0],
5071 MAX_SUPPORTED_CHANNEL_MASKS,
5072 &config->sample_rate,
5073 &in->supported_sample_rates[0],
5074 MAX_SUPPORTED_SAMPLE_RATES);
5075 if (ret != 0) {
5076 ret = -EINVAL;
5077 goto err_open;
5078 }
Eric Laurent74b55762017-07-09 17:04:53 -07005079 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005080 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005081 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005082 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5083 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5084 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5085 bool ret_error = false;
5086 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5087 from HAL is 8_24
5088 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5089 8_24 return error indicating supported format is 8_24
5090 *> In case of any other source requesting 24 bit or float return error
5091 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005092
vivek mehta57ff9b52016-04-28 14:13:08 -07005093 on error flinger will retry with supported format passed
5094 */
5095 if (source != AUDIO_SOURCE_UNPROCESSED) {
5096 config->format = AUDIO_FORMAT_PCM_16_BIT;
5097 ret_error = true;
5098 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5099 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5100 ret_error = true;
5101 }
5102
5103 if (ret_error) {
5104 ret = -EINVAL;
5105 goto err_open;
5106 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005107 }
5108
vivek mehta57ff9b52016-04-28 14:13:08 -07005109 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005110 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005113 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5114 if (config->sample_rate == 0)
5115 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5116 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5117 config->sample_rate != 8000) {
5118 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5119 ret = -EINVAL;
5120 goto err_open;
5121 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005122
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005123 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5124 config->format = AUDIO_FORMAT_PCM_16_BIT;
5125 ret = -EINVAL;
5126 goto err_open;
5127 }
5128
5129 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5130 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005131 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005132 } else if (is_usb_dev && may_use_hifi_record) {
5133 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5134 in->config = pcm_config_audio_capture;
5135 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005136 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5137 config->sample_rate,
5138 config->format,
5139 channel_count,
5140 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005141 in->config.period_size = buffer_size / frame_size;
5142 in->config.rate = config->sample_rate;
5143 in->af_period_multiplier = 1;
5144 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005145 } else {
5146 in->usecase = USECASE_AUDIO_RECORD;
5147 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005148 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005149 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005150#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005151 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005152#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005153 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005154 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005155 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005156 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005157 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5158 config->sample_rate,
5159 config->format,
5160 channel_count,
5161 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005162 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005163 in->config.rate = config->sample_rate;
5164 in->af_period_multiplier = 1;
5165 } else {
5166 // period size is left untouched for rt mode playback
5167 in->config = pcm_config_audio_capture_rt;
5168 in->af_period_multiplier = af_period_multiplier;
5169 }
5170 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5171 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005172 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005173 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5174 in->config = pcm_config_mmap_capture;
5175 in->stream.start = in_start;
5176 in->stream.stop = in_stop;
5177 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5178 in->stream.get_mmap_position = in_get_mmap_position;
5179 in->af_period_multiplier = 1;
5180 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005181 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005182 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005183 (config->sample_rate == 8000 ||
5184 config->sample_rate == 16000 ||
5185 config->sample_rate == 32000 ||
5186 config->sample_rate == 48000) &&
5187 channel_count == 1) {
5188 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5189 in->config = pcm_config_audio_capture;
5190 frame_size = audio_stream_in_frame_size(&in->stream);
5191 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5192 config->sample_rate,
5193 config->format,
5194 channel_count, false /*is_low_latency*/);
5195 in->config.period_size = buffer_size / frame_size;
5196 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5197 in->config.rate = config->sample_rate;
5198 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005199 } else {
5200 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005201 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005202 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5203 config->sample_rate,
5204 config->format,
5205 channel_count,
5206 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005207 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005208 in->config.rate = config->sample_rate;
5209 in->af_period_multiplier = 1;
5210 }
5211 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5212 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005213 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005215 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005216 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005217
Kevin Rocarda325aa22018-04-03 09:15:52 -07005218
5219 register_format(in->format, in->supported_formats);
5220 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5221 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5222
Andy Hungd13f0d32017-06-12 13:58:37 -07005223 in->error_log = error_log_create(
5224 ERROR_LOG_ENTRIES,
5225 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5226
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005227 /* This stream could be for sound trigger lab,
5228 get sound trigger pcm if present */
5229 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005231 lock_input_stream(in);
5232 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5233 pthread_mutex_lock(&adev->lock);
5234 in->card_status = adev->card_status;
5235 pthread_mutex_unlock(&adev->lock);
5236 pthread_mutex_unlock(&in->lock);
5237
vivek mehta4a824772017-06-08 19:05:49 -07005238 stream_app_type_cfg_init(&in->app_type_cfg);
5239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005241 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 return 0;
5243
5244err_open:
5245 free(in);
5246 *stream_in = NULL;
5247 return ret;
5248}
5249
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005250static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005251 struct audio_stream_in *stream)
5252{
Andy Hungd13f0d32017-06-12 13:58:37 -07005253 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005254 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005255
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005256 // must deregister from sndmonitor first to prevent races
5257 // between the callback and close_stream
5258 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005259 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005260
5261 error_log_destroy(in->error_log);
5262 in->error_log = NULL;
5263
Andy Hung0dbb52b2017-08-09 13:51:38 -07005264 pthread_mutex_destroy(&in->pre_lock);
5265 pthread_mutex_destroy(&in->lock);
5266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267 free(stream);
5268
5269 return;
5270}
5271
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005272static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005273{
5274 return 0;
5275}
5276
Andy Hung31aca912014-03-20 17:14:59 -07005277/* verifies input and output devices and their capabilities.
5278 *
5279 * This verification is required when enabling extended bit-depth or
5280 * sampling rates, as not all qcom products support it.
5281 *
5282 * Suitable for calling only on initialization such as adev_open().
5283 * It fills the audio_device use_case_table[] array.
5284 *
5285 * Has a side-effect that it needs to configure audio routing / devices
5286 * in order to power up the devices and read the device parameters.
5287 * It does not acquire any hw device lock. Should restore the devices
5288 * back to "normal state" upon completion.
5289 */
5290static int adev_verify_devices(struct audio_device *adev)
5291{
5292 /* enumeration is a bit difficult because one really wants to pull
5293 * the use_case, device id, etc from the hidden pcm_device_table[].
5294 * In this case there are the following use cases and device ids.
5295 *
5296 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5297 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005298 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005299 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5300 * [USECASE_AUDIO_RECORD] = {0, 0},
5301 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5302 * [USECASE_VOICE_CALL] = {2, 2},
5303 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005304 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005305 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5306 */
5307
5308 /* should be the usecases enabled in adev_open_input_stream() */
5309 static const int test_in_usecases[] = {
5310 USECASE_AUDIO_RECORD,
5311 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5312 };
5313 /* should be the usecases enabled in adev_open_output_stream()*/
5314 static const int test_out_usecases[] = {
5315 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5316 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5317 };
5318 static const usecase_type_t usecase_type_by_dir[] = {
5319 PCM_PLAYBACK,
5320 PCM_CAPTURE,
5321 };
5322 static const unsigned flags_by_dir[] = {
5323 PCM_OUT,
5324 PCM_IN,
5325 };
5326
5327 size_t i;
5328 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005329 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005330 char info[512]; /* for possible debug info */
5331
5332 for (dir = 0; dir < 2; ++dir) {
5333 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5334 const unsigned flags_dir = flags_by_dir[dir];
5335 const size_t testsize =
5336 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5337 const int *testcases =
5338 dir ? test_in_usecases : test_out_usecases;
5339 const audio_devices_t audio_device =
5340 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5341
5342 for (i = 0; i < testsize; ++i) {
5343 const audio_usecase_t audio_usecase = testcases[i];
5344 int device_id;
5345 snd_device_t snd_device;
5346 struct pcm_params **pparams;
5347 struct stream_out out;
5348 struct stream_in in;
5349 struct audio_usecase uc_info;
5350 int retval;
5351
5352 pparams = &adev->use_case_table[audio_usecase];
5353 pcm_params_free(*pparams); /* can accept null input */
5354 *pparams = NULL;
5355
5356 /* find the device ID for the use case (signed, for error) */
5357 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5358 if (device_id < 0)
5359 continue;
5360
5361 /* prepare structures for device probing */
5362 memset(&uc_info, 0, sizeof(uc_info));
5363 uc_info.id = audio_usecase;
5364 uc_info.type = usecase_type;
5365 if (dir) {
5366 adev->active_input = &in;
5367 memset(&in, 0, sizeof(in));
5368 in.device = audio_device;
5369 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5370 uc_info.stream.in = &in;
5371 } else {
5372 adev->active_input = NULL;
5373 }
5374 memset(&out, 0, sizeof(out));
5375 out.devices = audio_device; /* only field needed in select_devices */
5376 uc_info.stream.out = &out;
5377 uc_info.devices = audio_device;
5378 uc_info.in_snd_device = SND_DEVICE_NONE;
5379 uc_info.out_snd_device = SND_DEVICE_NONE;
5380 list_add_tail(&adev->usecase_list, &uc_info.list);
5381
5382 /* select device - similar to start_(in/out)put_stream() */
5383 retval = select_devices(adev, audio_usecase);
5384 if (retval >= 0) {
5385 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5386#if LOG_NDEBUG == 0
5387 if (*pparams) {
5388 ALOGV("%s: (%s) card %d device %d", __func__,
5389 dir ? "input" : "output", card_id, device_id);
5390 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005391 } else {
5392 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5393 }
5394#endif
5395 }
5396
5397 /* deselect device - similar to stop_(in/out)put_stream() */
5398 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005399 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005400 /* 2. Disable the rx device */
5401 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005402 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005403 list_remove(&uc_info.list);
5404 }
5405 }
5406 adev->active_input = NULL; /* restore adev state */
5407 return 0;
5408}
5409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005410static int adev_close(hw_device_t *device)
5411{
Andy Hung31aca912014-03-20 17:14:59 -07005412 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005413 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005414
5415 if (!adev)
5416 return 0;
5417
5418 pthread_mutex_lock(&adev_init_lock);
5419
5420 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005421 audio_extn_snd_mon_unregister_listener(adev);
5422 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005423 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005424 audio_route_free(adev->audio_route);
5425 free(adev->snd_dev_ref_cnt);
5426 platform_deinit(adev->platform);
5427 audio_extn_extspk_deinit(adev->extspk);
5428 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005429 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005430 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5431 pcm_params_free(adev->use_case_table[i]);
5432 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005433 if (adev->adm_deinit)
5434 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005435 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005436 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005437 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005438
5439 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441 return 0;
5442}
5443
Glenn Kasten4f993392014-05-14 07:30:48 -07005444/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5445 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5446 * just that it _might_ work.
5447 */
5448static int period_size_is_plausible_for_low_latency(int period_size)
5449{
5450 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005451 case 48:
5452 case 96:
5453 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005454 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005455 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005456 case 240:
5457 case 320:
5458 case 480:
5459 return 1;
5460 default:
5461 return 0;
5462 }
5463}
5464
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005465static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5466{
5467 int card;
5468 card_status_t status;
5469
5470 if (!parms)
5471 return;
5472
5473 if (parse_snd_card_status(parms, &card, &status) < 0)
5474 return;
5475
5476 pthread_mutex_lock(&adev->lock);
5477 bool valid_cb = (card == adev->snd_card);
5478 if (valid_cb) {
5479 if (adev->card_status != status) {
5480 adev->card_status = status;
5481 platform_snd_card_update(adev->platform, status);
5482 }
5483 }
5484 pthread_mutex_unlock(&adev->lock);
5485 return;
5486}
5487
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005488/* out and adev lock held */
5489static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5490{
5491 struct audio_usecase *uc_info;
5492 float left_p;
5493 float right_p;
5494 audio_devices_t devices;
5495
5496 uc_info = get_usecase_from_list(adev, out->usecase);
5497 if (uc_info == NULL) {
5498 ALOGE("%s: Could not find the usecase (%d) in the list",
5499 __func__, out->usecase);
5500 return -EINVAL;
5501 }
5502
5503 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5504 out->usecase, use_case_table[out->usecase]);
5505
5506 if (restore) {
5507 // restore A2DP device for active usecases and unmute if required
5508 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5509 !is_a2dp_device(uc_info->out_snd_device)) {
5510 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5511 select_devices(adev, uc_info->id);
5512 pthread_mutex_lock(&out->compr_mute_lock);
5513 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5514 (out->a2dp_compress_mute)) {
5515 out->a2dp_compress_mute = false;
5516 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5517 }
5518 pthread_mutex_unlock(&out->compr_mute_lock);
5519 }
5520 } else {
5521 // mute compress stream if suspended
5522 pthread_mutex_lock(&out->compr_mute_lock);
5523 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5524 (!out->a2dp_compress_mute)) {
5525 if (!out->standby) {
5526 ALOGD("%s: selecting speaker and muting stream", __func__);
5527 devices = out->devices;
5528 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5529 left_p = out->volume_l;
5530 right_p = out->volume_r;
5531 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5532 compress_pause(out->compr);
5533 set_compr_volume(&out->stream, 0.0f, 0.0f);
5534 out->a2dp_compress_mute = true;
5535 select_devices(adev, out->usecase);
5536 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5537 compress_resume(out->compr);
5538 out->devices = devices;
5539 out->volume_l = left_p;
5540 out->volume_r = right_p;
5541 }
5542 }
5543 pthread_mutex_unlock(&out->compr_mute_lock);
5544 }
5545 ALOGV("%s: exit", __func__);
5546 return 0;
5547}
5548
5549int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5550{
5551 int ret = 0;
5552
5553 lock_output_stream(out);
5554 pthread_mutex_lock(&adev->lock);
5555
5556 ret = check_a2dp_restore_l(adev, out, restore);
5557
5558 pthread_mutex_unlock(&adev->lock);
5559 pthread_mutex_unlock(&out->lock);
5560 return ret;
5561}
5562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005563static int adev_open(const hw_module_t *module, const char *name,
5564 hw_device_t **device)
5565{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005566 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567
Eric Laurent2bafff12016-03-17 12:17:23 -07005568 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005570 pthread_mutex_lock(&adev_init_lock);
5571 if (audio_device_ref_count != 0) {
5572 *device = &adev->device.common;
5573 audio_device_ref_count++;
5574 ALOGV("%s: returning existing instance of adev", __func__);
5575 ALOGV("%s: exit", __func__);
5576 pthread_mutex_unlock(&adev_init_lock);
5577 return 0;
5578 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005579 adev = calloc(1, sizeof(struct audio_device));
5580
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005581 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005583 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5584 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5585 adev->device.common.module = (struct hw_module_t *)module;
5586 adev->device.common.close = adev_close;
5587
5588 adev->device.init_check = adev_init_check;
5589 adev->device.set_voice_volume = adev_set_voice_volume;
5590 adev->device.set_master_volume = adev_set_master_volume;
5591 adev->device.get_master_volume = adev_get_master_volume;
5592 adev->device.set_master_mute = adev_set_master_mute;
5593 adev->device.get_master_mute = adev_get_master_mute;
5594 adev->device.set_mode = adev_set_mode;
5595 adev->device.set_mic_mute = adev_set_mic_mute;
5596 adev->device.get_mic_mute = adev_get_mic_mute;
5597 adev->device.set_parameters = adev_set_parameters;
5598 adev->device.get_parameters = adev_get_parameters;
5599 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5600 adev->device.open_output_stream = adev_open_output_stream;
5601 adev->device.close_output_stream = adev_close_output_stream;
5602 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604 adev->device.close_input_stream = adev_close_input_stream;
5605 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005606 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005607
5608 /* Set the default route before the PCM stream is opened */
5609 pthread_mutex_lock(&adev->lock);
5610 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005611 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005612 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005614 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005615 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005616 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005617 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005618 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005619 pthread_mutex_unlock(&adev->lock);
5620
5621 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005622 adev->platform = platform_init(adev);
5623 if (!adev->platform) {
5624 free(adev->snd_dev_ref_cnt);
5625 free(adev);
5626 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5627 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005628 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005629 return -EINVAL;
5630 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005631 adev->extspk = audio_extn_extspk_init(adev);
5632
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005633 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5634 if (adev->visualizer_lib == NULL) {
5635 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5636 } else {
5637 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5638 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005639 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005640 "visualizer_hal_start_output");
5641 adev->visualizer_stop_output =
5642 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5643 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005644 }
5645
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005646 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5647 if (adev->offload_effects_lib == NULL) {
5648 ALOGW("%s: DLOPEN failed for %s", __func__,
5649 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5650 } else {
5651 ALOGV("%s: DLOPEN successful for %s", __func__,
5652 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5653 adev->offload_effects_start_output =
5654 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5655 "offload_effects_bundle_hal_start_output");
5656 adev->offload_effects_stop_output =
5657 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5658 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005659 }
5660
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005661 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5662 if (adev->adm_lib == NULL) {
5663 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5664 } else {
5665 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5666 adev->adm_init = (adm_init_t)
5667 dlsym(adev->adm_lib, "adm_init");
5668 adev->adm_deinit = (adm_deinit_t)
5669 dlsym(adev->adm_lib, "adm_deinit");
5670 adev->adm_register_input_stream = (adm_register_input_stream_t)
5671 dlsym(adev->adm_lib, "adm_register_input_stream");
5672 adev->adm_register_output_stream = (adm_register_output_stream_t)
5673 dlsym(adev->adm_lib, "adm_register_output_stream");
5674 adev->adm_deregister_stream = (adm_deregister_stream_t)
5675 dlsym(adev->adm_lib, "adm_deregister_stream");
5676 adev->adm_request_focus = (adm_request_focus_t)
5677 dlsym(adev->adm_lib, "adm_request_focus");
5678 adev->adm_abandon_focus = (adm_abandon_focus_t)
5679 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005680 adev->adm_set_config = (adm_set_config_t)
5681 dlsym(adev->adm_lib, "adm_set_config");
5682 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5683 dlsym(adev->adm_lib, "adm_request_focus_v2");
5684 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5685 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5686 adev->adm_on_routing_change = (adm_on_routing_change_t)
5687 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005688 }
5689
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005690 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005691 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005693 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005694
Andy Hung31aca912014-03-20 17:14:59 -07005695 if (k_enable_extended_precision)
5696 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005697
Glenn Kasten4f993392014-05-14 07:30:48 -07005698 char value[PROPERTY_VALUE_MAX];
5699 int trial;
5700 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5701 trial = atoi(value);
5702 if (period_size_is_plausible_for_low_latency(trial)) {
5703 pcm_config_low_latency.period_size = trial;
5704 pcm_config_low_latency.start_threshold = trial / 4;
5705 pcm_config_low_latency.avail_min = trial / 4;
5706 configured_low_latency_capture_period_size = trial;
5707 }
5708 }
5709 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5710 trial = atoi(value);
5711 if (period_size_is_plausible_for_low_latency(trial)) {
5712 configured_low_latency_capture_period_size = trial;
5713 }
5714 }
5715
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005716 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5717
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005718 // commented as full set of app type cfg is sent from platform
5719 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005720 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005721
5722 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5723 af_period_multiplier = atoi(value);
5724 if (af_period_multiplier < 0) {
5725 af_period_multiplier = 2;
5726 } else if (af_period_multiplier > 4) {
5727 af_period_multiplier = 4;
5728 }
5729 ALOGV("new period_multiplier = %d", af_period_multiplier);
5730 }
5731
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005732 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005733 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005734
vivek mehta1a9b7c02015-06-25 11:49:38 -07005735 pthread_mutex_unlock(&adev_init_lock);
5736
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005737 if (adev->adm_init)
5738 adev->adm_data = adev->adm_init();
5739
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005740 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005741 audio_extn_snd_mon_init();
5742 pthread_mutex_lock(&adev->lock);
5743 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5744 adev->card_status = CARD_STATUS_ONLINE;
5745 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005746 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005747
Eric Laurent2bafff12016-03-17 12:17:23 -07005748 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005749 return 0;
5750}
5751
5752static struct hw_module_methods_t hal_module_methods = {
5753 .open = adev_open,
5754};
5755
5756struct audio_module HAL_MODULE_INFO_SYM = {
5757 .common = {
5758 .tag = HARDWARE_MODULE_TAG,
5759 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5760 .hal_api_version = HARDWARE_HAL_API_VERSION,
5761 .id = AUDIO_HARDWARE_MODULE_ID,
5762 .name = "QCOM Audio HAL",
5763 .author = "Code Aurora Forum",
5764 .methods = &hal_module_methods,
5765 },
5766};