blob: 3425eb9f41515fdabb3cf3984ccc3fb2e888f895 [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;
Andy Hung11f10e22018-10-19 17:47:12 -0700604 char mixer_path[MIXER_PATH_MAX_LENGTH];
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);
Andy Hung11f10e22018-10-19 17:47:12 -0700617
618 // we shouldn't truncate mixer_path
619 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
620 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
621 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800622 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700623
yixuanjiang509f0a72018-09-06 18:37:23 +0800624 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700625 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700626 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800628 ALOGV("%s: exit", __func__);
629 return 0;
630}
631
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800632int disable_audio_route(struct audio_device *adev,
633 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800634{
yixuanjiang509f0a72018-09-06 18:37:23 +0800635 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700636 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800637
638 if (usecase == NULL)
639 return -EINVAL;
640
641 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800642 if (usecase->type == PCM_CAPTURE)
643 snd_device = usecase->in_snd_device;
644 else
645 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700646
647 // we shouldn't truncate mixer_path
648 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
649 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
650 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800651 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700652 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700653
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700654 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000655 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800657 ALOGV("%s: exit", __func__);
658 return 0;
659}
660
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800661int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700662 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800663{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700664 int i, num_devices = 0;
665 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800666 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800667 if (snd_device < SND_DEVICE_MIN ||
668 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800669 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800670 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700673 platform_send_audio_calibration(adev->platform, snd_device);
674
vivek mehtade4849c2016-03-03 17:23:38 -0800675 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700676 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700677 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800678 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 }
680
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700681 /* due to the possibility of calibration overwrite between listen
682 and audio, notify sound trigger hal before audio calibration is sent */
683 audio_extn_sound_trigger_update_device_status(snd_device,
684 ST_EVENT_SND_DEVICE_BUSY);
685
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 if (audio_extn_spkr_prot_is_enabled())
687 audio_extn_spkr_prot_calib_cancel(adev);
688
zhaoyang yin4211fad2015-06-04 21:13:25 +0800689 audio_extn_dsm_feedback_enable(adev, snd_device, true);
690
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700691 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800692 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800693 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
695 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700696 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800697 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700698 }
699 if (audio_extn_spkr_prot_start_processing(snd_device)) {
700 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800701 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700703 } else if (platform_can_split_snd_device(snd_device,
704 &num_devices,
705 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700706 for (i = 0; i < num_devices; i++) {
707 enable_snd_device(adev, new_snd_devices[i]);
708 }
vivek mehtab6506412015-08-07 16:55:17 -0700709 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700710 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800711 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
712 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
713 ALOGE(" %s: Invalid sound device returned", __func__);
714 goto on_error;
715 }
Ed Tam70b5c142016-03-21 19:14:29 -0700716
Eric Laurent2e140aa2016-06-30 17:14:46 -0700717 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700718
719 if (is_a2dp_device(snd_device) &&
720 (audio_extn_a2dp_start_playback() < 0)) {
721 ALOGE("%s: failed to configure A2DP control path", __func__);
722 goto on_error;
723 }
724
vivek mehtade4849c2016-03-03 17:23:38 -0800725 audio_route_apply_and_update_path(adev->audio_route, device_name);
726 }
727on_success:
728 adev->snd_dev_ref_cnt[snd_device]++;
729 ret_val = 0;
730on_error:
731 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800732}
733
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800734int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700735 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700737 int i, num_devices = 0;
738 snd_device_t new_snd_devices[2];
739
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800740 if (snd_device < SND_DEVICE_MIN ||
741 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800742 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800743 return -EINVAL;
744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
746 ALOGE("%s: device ref cnt is already 0", __func__);
747 return -EINVAL;
748 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800749 audio_extn_tfa_98xx_disable_speaker(snd_device);
750
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 adev->snd_dev_ref_cnt[snd_device]--;
752 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800753 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800754
755 if (is_a2dp_device(snd_device))
756 audio_extn_a2dp_stop_playback();
757
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700758 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800759 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700760 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700761 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
762 audio_extn_spkr_prot_is_enabled()) {
763 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700764
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700765 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
766 // and does not use speaker swap. As this code causes a problem with device enable ref
767 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700768 // when speaker device is disabled, reset swap.
769 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700770 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700771
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700772 } else if (platform_can_split_snd_device(snd_device,
773 &num_devices,
774 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700775 for (i = 0; i < num_devices; i++) {
776 disable_snd_device(adev, new_snd_devices[i]);
777 }
vivek mehtab6506412015-08-07 16:55:17 -0700778 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700779 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800780 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
781 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
782 ALOGE(" %s: Invalid sound device returned", __func__);
783 return -EINVAL;
784 }
785
Eric Laurent2e140aa2016-06-30 17:14:46 -0700786 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800787 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700788 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700789 audio_extn_sound_trigger_update_device_status(snd_device,
790 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700791 }
vivek mehtab6506412015-08-07 16:55:17 -0700792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793 return 0;
794}
795
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700796/*
797 legend:
798 uc - existing usecase
799 new_uc - new usecase
800 d1, d11, d2 - SND_DEVICE enums
801 a1, a2 - corresponding ANDROID device enums
802 B, B1, B2 - backend strings
803
804case 1
805 uc->dev d1 (a1) B1
806 new_uc->dev d1 (a1), d2 (a2) B1, B2
807
808 resolution: disable and enable uc->dev on d1
809
810case 2
811 uc->dev d1 (a1) B1
812 new_uc->dev d11 (a1) B1
813
814 resolution: need to switch uc since d1 and d11 are related
815 (e.g. speaker and voice-speaker)
816 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
817
818case 3
819 uc->dev d1 (a1) B1
820 new_uc->dev d2 (a2) B2
821
822 resolution: no need to switch uc
823
824case 4
825 uc->dev d1 (a1) B
826 new_uc->dev 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. e.g. if offload is on speaker device using
831 QUAD_MI2S backend and a low-latency stream is started on voice-handset
832 using the same backend, offload must also be switched to voice-handset.
833
834case 5
835 uc->dev d1 (a1) B
836 new_uc->dev d1 (a1), d2 (a2) B
837
838 resolution: disable enable uc-dev on d2 since backends match
839 we cannot enable two streams on two different devices if they
840 share the same backend.
841
842case 6
843 uc->dev d1 a1 B1
844 new_uc->dev d2 a1 B2
845
846 resolution: no need to switch
847
848case 7
849
850 uc->dev d1 (a1), d2 (a2) B1, B2
851 new_uc->dev d1 B1
852
853 resolution: no need to switch
854
855*/
856static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
857 struct audio_usecase *new_uc,
858 snd_device_t new_snd_device)
859{
860 audio_devices_t a1 = uc->stream.out->devices;
861 audio_devices_t a2 = new_uc->stream.out->devices;
862
863 snd_device_t d1 = uc->out_snd_device;
864 snd_device_t d2 = new_snd_device;
865
866 // Treat as a special case when a1 and a2 are not disjoint
867 if ((a1 != a2) && (a1 & a2)) {
868 snd_device_t d3[2];
869 int num_devices = 0;
870 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
871 &num_devices,
872 d3);
873 if (ret < 0) {
874 if (ret != -ENOSYS) {
875 ALOGW("%s failed to split snd_device %d",
876 __func__,
877 popcount(a1) > 1 ? d1 : d2);
878 }
879 goto end;
880 }
881
882 // NB: case 7 is hypothetical and isn't a practical usecase yet.
883 // But if it does happen, we need to give priority to d2 if
884 // the combo devices active on the existing usecase share a backend.
885 // This is because we cannot have a usecase active on a combo device
886 // and a new usecase requests one device in this combo pair.
887 if (platform_check_backends_match(d3[0], d3[1])) {
888 return d2; // case 5
889 } else {
890 return d1; // case 1
891 }
892 } else {
893 if (platform_check_backends_match(d1, d2)) {
894 return d2; // case 2, 4
895 } else {
896 return d1; // case 6, 3
897 }
898 }
899
900end:
901 return d2; // return whatever was calculated before.
902}
903
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700904static void check_and_route_playback_usecases(struct audio_device *adev,
905 struct audio_usecase *uc_info,
906 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907{
908 struct listnode *node;
909 struct audio_usecase *usecase;
910 bool switch_device[AUDIO_USECASE_MAX];
911 int i, num_uc_to_switch = 0;
912
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700913 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
914 uc_info,
915 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700916
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800917 /* For a2dp device reconfigure all active sessions
918 * with new AFE encoder format based on a2dp state
919 */
920 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700921 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
922 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800923 audio_extn_a2dp_is_force_device_switch()) {
924 force_routing = true;
925 }
926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 /*
928 * This function is to make sure that all the usecases that are active on
929 * the hardware codec backend are always routed to any one device that is
930 * handled by the hardware codec.
931 * For example, if low-latency and deep-buffer usecases are currently active
932 * on speaker and out_set_parameters(headset) is received on low-latency
933 * output, then we have to make sure deep-buffer is also switched to headset,
934 * because of the limitation that both the devices cannot be enabled
935 * at the same time as they share the same backend.
936 */
937 /* Disable all the usecases on the shared backend other than the
938 specified usecase */
939 for (i = 0; i < AUDIO_USECASE_MAX; i++)
940 switch_device[i] = false;
941
942 list_for_each(node, &adev->usecase_list) {
943 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700944 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
945 continue;
946
947 if (force_routing ||
948 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700949 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
950 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700951 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
953 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700954 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 switch_device[usecase->id] = true;
957 num_uc_to_switch++;
958 }
959 }
960
961 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700962 list_for_each(node, &adev->usecase_list) {
963 usecase = node_to_item(node, struct audio_usecase, list);
964 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900966 }
967 }
968
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700969 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900970 list_for_each(node, &adev->usecase_list) {
971 usecase = node_to_item(node, struct audio_usecase, list);
972 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700973 d_device = derive_playback_snd_device(usecase, uc_info,
974 snd_device);
975 enable_snd_device(adev, d_device);
976 /* Update the out_snd_device before enabling the audio route */
977 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978 }
979 }
980
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700981 /* Re-route all the usecases on the shared backend other than the
982 specified usecase to new snd devices */
983 list_for_each(node, &adev->usecase_list) {
984 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700986 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 }
988 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 }
990}
991
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992static void check_and_route_capture_usecases(struct audio_device *adev,
993 struct audio_usecase *uc_info,
994 snd_device_t snd_device)
995{
996 struct listnode *node;
997 struct audio_usecase *usecase;
998 bool switch_device[AUDIO_USECASE_MAX];
999 int i, num_uc_to_switch = 0;
1000
vivek mehta4ed66e62016-04-15 23:33:34 -07001001 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1002
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
1018 if (usecase->type != PCM_PLAYBACK &&
1019 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001020 usecase->in_snd_device != snd_device &&
1021 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1023 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001024 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001026 switch_device[usecase->id] = true;
1027 num_uc_to_switch++;
1028 }
1029 }
1030
1031 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001032 list_for_each(node, &adev->usecase_list) {
1033 usecase = node_to_item(node, struct audio_usecase, list);
1034 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001035 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001036 }
1037 }
1038
1039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001042 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001043 }
1044 }
1045
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 /* Re-route all the usecases on the shared backend other than the
1047 specified usecase to new snd devices */
1048 list_for_each(node, &adev->usecase_list) {
1049 usecase = node_to_item(node, struct audio_usecase, list);
1050 /* Update the in_snd_device only before enabling the audio route */
1051 if (switch_device[usecase->id] ) {
1052 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001053 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001054 }
1055 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001056 }
1057}
1058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001060static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001062 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001063 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
1065 switch (channels) {
1066 /*
1067 * Do not handle stereo output in Multi-channel cases
1068 * Stereo case is handled in normal playback path
1069 */
1070 case 6:
1071 ALOGV("%s: HDMI supports 5.1", __func__);
1072 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1073 break;
1074 case 8:
1075 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1076 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1077 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1078 break;
1079 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001080 ALOGE("HDMI does not support multi channel playback");
1081 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082 break;
1083 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001084 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085}
1086
Andy Hung18859412017-08-09 11:47:21 -07001087static ssize_t read_usb_sup_sample_rates(bool is_playback,
1088 uint32_t *supported_sample_rates,
1089 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001090{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001091 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1092 supported_sample_rates,
1093 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001094#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001095 for (ssize_t i=0; i<count; i++) {
1096 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1097 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001098 }
1099#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001100 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001101}
1102
Haynes Mathew George569b7482017-05-08 14:44:27 -07001103static int read_usb_sup_channel_masks(bool is_playback,
1104 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001105 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001106{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001107 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001108 int channel_count;
1109 uint32_t num_masks = 0;
1110 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1111 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001112 }
Eric Laurent74b55762017-07-09 17:04:53 -07001113 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001114 // start from 2 channels as framework currently doesn't support mono.
1115 // TODO: consider only supporting channel index masks beyond stereo here.
1116 for (channel_count = FCC_2;
1117 channel_count <= channels && num_masks < max_masks;
1118 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001119 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1120 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001121 for (channel_count = FCC_2;
1122 channel_count <= channels && num_masks < max_masks;
1123 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001124 supported_channel_masks[num_masks++] =
1125 audio_channel_mask_for_index_assignment_from_count(channel_count);
1126 }
1127 } else {
1128 // For capture we report all supported channel masks from 1 channel up.
1129 channel_count = MIN_CHANNEL_COUNT;
1130 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1131 // indexed mask
1132 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1133 supported_channel_masks[num_masks++] =
1134 audio_channel_in_mask_from_count(channel_count);
1135 }
1136 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001137#ifdef NDEBUG
1138 for (size_t i = 0; i < num_masks; ++i) {
1139 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1140 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1141 }
1142#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001143 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001144}
1145
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001146static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 audio_format_t *supported_formats,
1148 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001149{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001150 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001151 switch (bitwidth) {
1152 case 24:
1153 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001155 break;
1156 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001157 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001158 break;
1159 case 16:
1160 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001161 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001162 break;
1163 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001164 ALOGV("%s: %s supported format %d", __func__,
1165 is_playback ? "P" : "C", bitwidth);
1166 return 1;
1167}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001168
Haynes Mathew George569b7482017-05-08 14:44:27 -07001169static int read_usb_sup_params_and_compare(bool is_playback,
1170 audio_format_t *format,
1171 audio_format_t *supported_formats,
1172 uint32_t max_formats,
1173 audio_channel_mask_t *mask,
1174 audio_channel_mask_t *supported_channel_masks,
1175 uint32_t max_masks,
1176 uint32_t *rate,
1177 uint32_t *supported_sample_rates,
1178 uint32_t max_rates) {
1179 int ret = 0;
1180 int num_formats;
1181 int num_masks;
1182 int num_rates;
1183 int i;
1184
1185 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1186 max_formats);
1187 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1188 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001189
Haynes Mathew George569b7482017-05-08 14:44:27 -07001190 num_rates = read_usb_sup_sample_rates(is_playback,
1191 supported_sample_rates, max_rates);
1192
1193#define LUT(table, len, what, dflt) \
1194 for (i=0; i<len && (table[i] != what); i++); \
1195 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1196
1197 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1198 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1199 LUT(supported_sample_rates, num_rates, *rate, 0);
1200
1201#undef LUT
1202 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001203}
1204
Andy Hungd9653bd2017-08-01 19:31:39 -07001205static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1206{
1207 // Check if usb is ready.
1208 // The usb device may have been removed quickly after insertion and hence
1209 // no longer available. This will show up as empty channel masks, or rates.
1210
1211 pthread_mutex_lock(&adev->lock);
1212 uint32_t supported_sample_rate;
1213
1214 // we consider usb ready if we can fetch at least one sample rate.
1215 const bool ready = read_usb_sup_sample_rates(
1216 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1217 pthread_mutex_unlock(&adev->lock);
1218 return ready;
1219}
1220
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001221static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1222{
1223 struct audio_usecase *usecase;
1224 struct listnode *node;
1225
1226 list_for_each(node, &adev->usecase_list) {
1227 usecase = node_to_item(node, struct audio_usecase, list);
1228 if (usecase->type == VOICE_CALL) {
1229 ALOGV("%s: usecase id %d", __func__, usecase->id);
1230 return usecase->id;
1231 }
1232 }
1233 return USECASE_INVALID;
1234}
1235
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001236struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1237 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238{
1239 struct audio_usecase *usecase;
1240 struct listnode *node;
1241
1242 list_for_each(node, &adev->usecase_list) {
1243 usecase = node_to_item(node, struct audio_usecase, list);
1244 if (usecase->id == uc_id)
1245 return usecase;
1246 }
1247 return NULL;
1248}
1249
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001250static bool force_device_switch(struct audio_usecase *usecase)
1251{
1252 if (usecase->stream.out == NULL) {
1253 ALOGE("%s: stream.out is NULL", __func__);
1254 return false;
1255 }
1256
1257 // Force all A2DP output devices to reconfigure for proper AFE encode format
1258 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1259 // in suspended state, hence try to trigger a retry when we again get a routing request.
1260 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1261 audio_extn_a2dp_is_force_device_switch()) {
1262 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1263 return true;
1264 }
1265
1266 return false;
1267}
1268
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001269int select_devices(struct audio_device *adev,
1270 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001271{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001272 snd_device_t out_snd_device = SND_DEVICE_NONE;
1273 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 struct audio_usecase *usecase = NULL;
1275 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001276 struct audio_usecase *hfp_usecase = NULL;
1277 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001278 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001280 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1281 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 usecase = get_usecase_from_list(adev, uc_id);
1284 if (usecase == NULL) {
1285 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1286 return -EINVAL;
1287 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001289 if ((usecase->type == VOICE_CALL) ||
1290 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001291 out_snd_device = platform_get_output_snd_device(adev->platform,
1292 usecase->stream.out->devices);
1293 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001294 usecase->devices = usecase->stream.out->devices;
1295 } else {
1296 /*
1297 * If the voice call is active, use the sound devices of voice call usecase
1298 * so that it would not result any device switch. All the usecases will
1299 * be switched to new device when select_devices() is called for voice call
1300 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001301 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001303 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001304 vc_usecase = get_usecase_from_list(adev,
1305 get_voice_usecase_id_from_list(adev));
1306 if ((vc_usecase != NULL) &&
1307 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1308 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 in_snd_device = vc_usecase->in_snd_device;
1310 out_snd_device = vc_usecase->out_snd_device;
1311 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001312 } else if (audio_extn_hfp_is_active(adev)) {
1313 hfp_ucid = audio_extn_hfp_get_usecase();
1314 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1315 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1316 in_snd_device = hfp_usecase->in_snd_device;
1317 out_snd_device = hfp_usecase->out_snd_device;
1318 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001319 }
1320 if (usecase->type == PCM_PLAYBACK) {
1321 usecase->devices = usecase->stream.out->devices;
1322 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001324 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001325
Eric Laurentb23d5282013-05-14 15:27:20 -07001326 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001327 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001328
1329 if (voip_usecase)
1330 voip_out = voip_usecase->stream.out;
1331
1332 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001333 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001334 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001335 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001336 select_devices(adev, adev->active_input->usecase);
1337 }
1338 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001339 } else if (usecase->type == PCM_CAPTURE) {
1340 usecase->devices = usecase->stream.in->device;
1341 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001342 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001343 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001344 if (adev->active_input &&
1345 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1346 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001347
1348 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1349 USECASE_AUDIO_PLAYBACK_VOIP);
1350
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001351 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001352 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1353 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001354 } else if (voip_usecase) {
1355 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001356 } else if (adev->primary_output) {
1357 out_device = adev->primary_output->devices;
1358 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001359 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001360 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001361 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001362 }
1363 }
1364
1365 if (out_snd_device == usecase->out_snd_device &&
1366 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001367 if (!force_device_switch(usecase))
1368 return 0;
1369 }
1370
1371 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1372 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1373 return 0;
1374 }
1375
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001376 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1377 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001378 (!audio_extn_a2dp_is_ready())) {
1379 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001380 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1381 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1382 else
1383 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 }
1385
juyuchen66c4ecf2018-08-06 15:39:34 +08001386 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1387 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1388 }
1389
Eric Laurent2bafff12016-03-17 12:17:23 -07001390 if (out_snd_device != SND_DEVICE_NONE &&
1391 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1392 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1393 __func__,
1394 use_case_table[uc_id],
1395 adev->last_logged_snd_device[uc_id][0],
1396 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1397 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1398 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1399 -1,
1400 out_snd_device,
1401 platform_get_snd_device_name(out_snd_device),
1402 platform_get_snd_device_acdb_id(out_snd_device));
1403 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1404 }
1405 if (in_snd_device != SND_DEVICE_NONE &&
1406 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1407 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1408 __func__,
1409 use_case_table[uc_id],
1410 adev->last_logged_snd_device[uc_id][1],
1411 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1412 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1413 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1414 -1,
1415 in_snd_device,
1416 platform_get_snd_device_name(in_snd_device),
1417 platform_get_snd_device_acdb_id(in_snd_device));
1418 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1419 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001421 /*
1422 * Limitation: While in call, to do a device switch we need to disable
1423 * and enable both RX and TX devices though one of them is same as current
1424 * device.
1425 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001426 if ((usecase->type == VOICE_CALL) &&
1427 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1428 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001429 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001430 /* Disable sidetone only if voice call already exists */
1431 if (voice_is_call_state_active(adev))
1432 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001433 }
1434
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 /* Disable current sound devices */
1436 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001437 disable_audio_route(adev, usecase);
1438 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 }
1440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001442 disable_audio_route(adev, usecase);
1443 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444 }
1445
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001446 /* Applicable only on the targets that has external modem.
1447 * New device information should be sent to modem before enabling
1448 * the devices to reduce in-call device switch time.
1449 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001450 if ((usecase->type == VOICE_CALL) &&
1451 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1452 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001453 status = platform_switch_voice_call_enable_device_config(adev->platform,
1454 out_snd_device,
1455 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001456 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001457
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 /* Enable new sound devices */
1459 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001460 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001461 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1462 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001463 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001464 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 }
1466
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001467 if (in_snd_device != SND_DEVICE_NONE) {
1468 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001469 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001470 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471
Eric Laurentb23d5282013-05-14 15:27:20 -07001472 if (usecase->type == VOICE_CALL)
1473 status = platform_switch_voice_call_device_post(adev->platform,
1474 out_snd_device,
1475 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001476
sangwoo170731f2013-06-08 15:36:36 +09001477 usecase->in_snd_device = in_snd_device;
1478 usecase->out_snd_device = out_snd_device;
1479
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001480 audio_extn_tfa_98xx_set_mode();
1481
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001482 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001483
Jasmine Cha70771b62018-05-15 15:02:43 +08001484 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001485
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001486 /* Applicable only on the targets that has external modem.
1487 * Enable device command should be sent to modem only after
1488 * enabling voice call mixer controls
1489 */
vivek mehta765eb642015-08-07 19:46:06 -07001490 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001491 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1492 out_snd_device,
1493 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001494 /* Enable sidetone only if voice call already exists */
1495 if (voice_is_call_state_active(adev))
1496 voice_set_sidetone(adev, out_snd_device, true);
1497 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001498
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001499 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001500 struct stream_out *voip_out = voip_usecase->stream.out;
1501 audio_extn_utils_send_app_type_gain(adev,
1502 voip_out->app_type_cfg.app_type,
1503 &voip_out->app_type_cfg.gain[0]);
1504 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505 return status;
1506}
1507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508static int stop_input_stream(struct stream_in *in)
1509{
1510 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 struct audio_usecase *uc_info;
1512 struct audio_device *adev = in->dev;
1513
Eric Laurent994a6932013-07-17 11:51:42 -07001514 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001516
1517 if (adev->active_input) {
1518 if (adev->active_input->usecase == in->usecase) {
1519 adev->active_input = NULL;
1520 } else {
1521 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1522 __func__,
1523 use_case_table[adev->active_input->usecase],
1524 use_case_table[in->usecase]);
1525 }
1526 }
1527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528 uc_info = get_usecase_from_list(adev, in->usecase);
1529 if (uc_info == NULL) {
1530 ALOGE("%s: Could not find the usecase (%d) in the list",
1531 __func__, in->usecase);
1532 return -EINVAL;
1533 }
1534
vivek mehta781065c2017-04-04 12:55:01 -07001535 /* Close in-call recording streams */
1536 voice_check_and_stop_incall_rec_usecase(adev, in);
1537
Eric Laurent150dbfe2013-02-27 14:31:02 -08001538 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001539 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001540
1541 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001542 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001543
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001544 list_remove(&uc_info->list);
1545 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546
Eric Laurent994a6932013-07-17 11:51:42 -07001547 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548 return ret;
1549}
1550
1551int start_input_stream(struct stream_in *in)
1552{
1553 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001554 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555 struct audio_usecase *uc_info;
1556 struct audio_device *adev = in->dev;
1557
Eric Laurent994a6932013-07-17 11:51:42 -07001558 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001559
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001560 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1561 return -EIO;
1562
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001563 if (in->card_status == CARD_STATUS_OFFLINE ||
1564 adev->card_status == CARD_STATUS_OFFLINE) {
1565 ALOGW("in->card_status or adev->card_status offline, try again");
1566 ret = -EAGAIN;
1567 goto error_config;
1568 }
1569
vivek mehta781065c2017-04-04 12:55:01 -07001570 /* Check if source matches incall recording usecase criteria */
1571 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1572 if (ret)
1573 goto error_config;
1574 else
1575 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1576
Eric Laurentb23d5282013-05-14 15:27:20 -07001577 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001578 if (in->pcm_device_id < 0) {
1579 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1580 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001581 ret = -EINVAL;
1582 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001584
1585 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1587 uc_info->id = in->usecase;
1588 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001589 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590 uc_info->devices = in->device;
1591 uc_info->in_snd_device = SND_DEVICE_NONE;
1592 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001594 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001595
Wei Wangf4837d52017-11-21 14:51:20 -08001596 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001597 audio_extn_perf_lock_acquire();
1598
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001599 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600
Eric Laurent0e46adf2016-12-16 12:49:24 -08001601 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001602 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001603 ALOGE("%s: pcm stream not ready", __func__);
1604 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001605 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001606 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001607 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001608 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1609 goto error_open;
1610 }
1611 } else {
1612 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1613 unsigned int pcm_open_retry_count = 0;
1614
1615 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1616 flags |= PCM_MMAP | PCM_NOIRQ;
1617 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1618 } else if (in->realtime) {
1619 flags |= PCM_MMAP | PCM_NOIRQ;
1620 }
1621
1622 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1623 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1624
1625 while (1) {
1626 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1627 flags, &in->config);
1628 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1629 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1630 if (in->pcm != NULL) {
1631 pcm_close(in->pcm);
1632 in->pcm = NULL;
1633 }
1634 if (pcm_open_retry_count-- == 0) {
1635 ret = -EIO;
1636 goto error_open;
1637 }
1638 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1639 continue;
1640 }
1641 break;
1642 }
1643
1644 ALOGV("%s: pcm_prepare", __func__);
1645 ret = pcm_prepare(in->pcm);
1646 if (ret < 0) {
1647 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001648 pcm_close(in->pcm);
1649 in->pcm = NULL;
1650 goto error_open;
1651 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001652 if (in->realtime) {
1653 ret = pcm_start(in->pcm);
1654 if (ret < 0) {
1655 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1656 pcm_close(in->pcm);
1657 in->pcm = NULL;
1658 goto error_open;
1659 }
1660 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001661 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001662 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001663 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001664 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001665 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001666
Eric Laurent0e46adf2016-12-16 12:49:24 -08001667 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001668
1669error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001671 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001672 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001673
1674error_config:
1675 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001676 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001677 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678}
1679
Eric Laurenta1478072015-09-21 17:21:52 -07001680void lock_input_stream(struct stream_in *in)
1681{
1682 pthread_mutex_lock(&in->pre_lock);
1683 pthread_mutex_lock(&in->lock);
1684 pthread_mutex_unlock(&in->pre_lock);
1685}
1686
1687void lock_output_stream(struct stream_out *out)
1688{
1689 pthread_mutex_lock(&out->pre_lock);
1690 pthread_mutex_lock(&out->lock);
1691 pthread_mutex_unlock(&out->pre_lock);
1692}
1693
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001694/* must be called with out->lock locked */
1695static int send_offload_cmd_l(struct stream_out* out, int command)
1696{
1697 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1698
1699 ALOGVV("%s %d", __func__, command);
1700
1701 cmd->cmd = command;
1702 list_add_tail(&out->offload_cmd_list, &cmd->node);
1703 pthread_cond_signal(&out->offload_cond);
1704 return 0;
1705}
1706
1707/* must be called iwth out->lock locked */
1708static void stop_compressed_output_l(struct stream_out *out)
1709{
1710 out->offload_state = OFFLOAD_STATE_IDLE;
1711 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001712 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001713 if (out->compr != NULL) {
1714 compress_stop(out->compr);
1715 while (out->offload_thread_blocked) {
1716 pthread_cond_wait(&out->cond, &out->lock);
1717 }
1718 }
1719}
1720
1721static void *offload_thread_loop(void *context)
1722{
1723 struct stream_out *out = (struct stream_out *) context;
1724 struct listnode *item;
1725
1726 out->offload_state = OFFLOAD_STATE_IDLE;
1727 out->playback_started = 0;
1728
1729 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1730 set_sched_policy(0, SP_FOREGROUND);
1731 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1732
1733 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001734 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001735 for (;;) {
1736 struct offload_cmd *cmd = NULL;
1737 stream_callback_event_t event;
1738 bool send_callback = false;
1739
1740 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1741 __func__, list_empty(&out->offload_cmd_list),
1742 out->offload_state);
1743 if (list_empty(&out->offload_cmd_list)) {
1744 ALOGV("%s SLEEPING", __func__);
1745 pthread_cond_wait(&out->offload_cond, &out->lock);
1746 ALOGV("%s RUNNING", __func__);
1747 continue;
1748 }
1749
1750 item = list_head(&out->offload_cmd_list);
1751 cmd = node_to_item(item, struct offload_cmd, node);
1752 list_remove(item);
1753
1754 ALOGVV("%s STATE %d CMD %d out->compr %p",
1755 __func__, out->offload_state, cmd->cmd, out->compr);
1756
1757 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1758 free(cmd);
1759 break;
1760 }
1761
1762 if (out->compr == NULL) {
1763 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001764 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 pthread_cond_signal(&out->cond);
1766 continue;
1767 }
1768 out->offload_thread_blocked = true;
1769 pthread_mutex_unlock(&out->lock);
1770 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001771 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1773 compress_wait(out->compr, -1);
1774 send_callback = true;
1775 event = STREAM_CBK_EVENT_WRITE_READY;
1776 break;
1777 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001778 compress_next_track(out->compr);
1779 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 send_callback = true;
1781 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001782 /* Resend the metadata for next iteration */
1783 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 break;
1785 case OFFLOAD_CMD_DRAIN:
1786 compress_drain(out->compr);
1787 send_callback = true;
1788 event = STREAM_CBK_EVENT_DRAIN_READY;
1789 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001790 case OFFLOAD_CMD_ERROR:
1791 send_callback = true;
1792 event = STREAM_CBK_EVENT_ERROR;
1793 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 default:
1795 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1796 break;
1797 }
Eric Laurenta1478072015-09-21 17:21:52 -07001798 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 out->offload_thread_blocked = false;
1800 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001801 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001802 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001804 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 free(cmd);
1806 }
1807
1808 pthread_cond_signal(&out->cond);
1809 while (!list_empty(&out->offload_cmd_list)) {
1810 item = list_head(&out->offload_cmd_list);
1811 list_remove(item);
1812 free(node_to_item(item, struct offload_cmd, node));
1813 }
1814 pthread_mutex_unlock(&out->lock);
1815
1816 return NULL;
1817}
1818
1819static int create_offload_callback_thread(struct stream_out *out)
1820{
1821 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1822 list_init(&out->offload_cmd_list);
1823 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1824 offload_thread_loop, out);
1825 return 0;
1826}
1827
1828static int destroy_offload_callback_thread(struct stream_out *out)
1829{
Eric Laurenta1478072015-09-21 17:21:52 -07001830 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 stop_compressed_output_l(out);
1832 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1833
1834 pthread_mutex_unlock(&out->lock);
1835 pthread_join(out->offload_thread, (void **) NULL);
1836 pthread_cond_destroy(&out->offload_cond);
1837
1838 return 0;
1839}
1840
Eric Laurent07eeafd2013-10-06 12:52:49 -07001841static bool allow_hdmi_channel_config(struct audio_device *adev)
1842{
1843 struct listnode *node;
1844 struct audio_usecase *usecase;
1845 bool ret = true;
1846
1847 list_for_each(node, &adev->usecase_list) {
1848 usecase = node_to_item(node, struct audio_usecase, list);
1849 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1850 /*
1851 * If voice call is already existing, do not proceed further to avoid
1852 * disabling/enabling both RX and TX devices, CSD calls, etc.
1853 * Once the voice call done, the HDMI channels can be configured to
1854 * max channels of remaining use cases.
1855 */
1856 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001857 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001858 __func__);
1859 ret = false;
1860 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001861 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1862 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001863 "no change in HDMI channels", __func__);
1864 ret = false;
1865 break;
1866 }
1867 }
1868 }
1869 return ret;
1870}
1871
1872static int check_and_set_hdmi_channels(struct audio_device *adev,
1873 unsigned int channels)
1874{
1875 struct listnode *node;
1876 struct audio_usecase *usecase;
1877
1878 /* Check if change in HDMI channel config is allowed */
1879 if (!allow_hdmi_channel_config(adev))
1880 return 0;
1881
1882 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001883 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001884 return 0;
1885 }
1886
1887 platform_set_hdmi_channels(adev->platform, channels);
1888 adev->cur_hdmi_channels = channels;
1889
1890 /*
1891 * Deroute all the playback streams routed to HDMI so that
1892 * the back end is deactivated. Note that backend will not
1893 * be deactivated if any one stream is connected to it.
1894 */
1895 list_for_each(node, &adev->usecase_list) {
1896 usecase = node_to_item(node, struct audio_usecase, list);
1897 if (usecase->type == PCM_PLAYBACK &&
1898 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001899 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001900 }
1901 }
1902
1903 /*
1904 * Enable all the streams disabled above. Now the HDMI backend
1905 * will be activated with new channel configuration
1906 */
1907 list_for_each(node, &adev->usecase_list) {
1908 usecase = node_to_item(node, struct audio_usecase, list);
1909 if (usecase->type == PCM_PLAYBACK &&
1910 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001911 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001912 }
1913 }
1914
1915 return 0;
1916}
1917
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001918static int check_and_set_usb_service_interval(struct audio_device *adev,
1919 struct audio_usecase *uc_info,
1920 bool min)
1921{
1922 struct listnode *node;
1923 struct audio_usecase *usecase;
1924 bool switch_usecases = false;
1925 bool reconfig = false;
1926
1927 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1928 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1929 return -1;
1930
1931 /* set if the valid usecase do not already exist */
1932 list_for_each(node, &adev->usecase_list) {
1933 usecase = node_to_item(node, struct audio_usecase, list);
1934 if (usecase->type == PCM_PLAYBACK &&
1935 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1936 switch (usecase->id) {
1937 case USECASE_AUDIO_PLAYBACK_MMAP:
1938 case USECASE_AUDIO_PLAYBACK_ULL:
1939 // cannot reconfig while mmap/ull is present.
1940 return -1;
1941 default:
1942 switch_usecases = true;
1943 break;
1944 }
1945 }
1946 if (switch_usecases)
1947 break;
1948 }
1949 /*
1950 * client can try to set service interval in start_output_stream
1951 * to min or to 0 (i.e reset) in stop_output_stream .
1952 */
1953 unsigned long service_interval =
1954 audio_extn_usb_find_service_interval(min, true /*playback*/);
1955 int ret = platform_set_usb_service_interval(adev->platform,
1956 true /*playback*/,
1957 service_interval,
1958 &reconfig);
1959 /* no change or not supported or no active usecases */
1960 if (ret || !reconfig || !switch_usecases)
1961 return -1;
1962 return 0;
1963#undef VALID_USECASE
1964}
1965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966static int stop_output_stream(struct stream_out *out)
1967{
1968 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 struct audio_usecase *uc_info;
1970 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001971 bool has_voip_usecase =
1972 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973
Eric Laurent994a6932013-07-17 11:51:42 -07001974 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001975 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001976 uc_info = get_usecase_from_list(adev, out->usecase);
1977 if (uc_info == NULL) {
1978 ALOGE("%s: Could not find the usecase (%d) in the list",
1979 __func__, out->usecase);
1980 return -EINVAL;
1981 }
1982
Haynes Mathew George41f86652014-06-17 14:22:15 -07001983 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1984 if (adev->visualizer_stop_output != NULL)
1985 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1986 if (adev->offload_effects_stop_output != NULL)
1987 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001988 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1989 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1990 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001991 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001992
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07001993 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
1994 voice_set_device_mute_flag(adev, false);
1995
Eric Laurent150dbfe2013-02-27 14:31:02 -08001996 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001997 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001998
1999 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002000 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002002 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003
Eric Laurent0499d4f2014-08-25 22:39:29 -05002004 audio_extn_extspk_update(adev->extspk);
2005
Eric Laurent07eeafd2013-10-06 12:52:49 -07002006 /* Must be called after removing the usecase from list */
2007 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2008 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002009 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002010 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2011 if (ret == 0) {
2012 /* default service interval was successfully updated,
2013 reopen USB backend with new service interval */
2014 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2015 }
2016 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002017 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002018
HW Lee88512e92018-06-12 15:26:09 +08002019 if (has_voip_usecase ||
2020 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2021 struct listnode *node;
2022 struct audio_usecase *usecase;
2023 list_for_each(node, &adev->usecase_list) {
2024 usecase = node_to_item(node, struct audio_usecase, list);
2025 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2026 continue;
2027
2028 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2029 __func__, usecase->id, use_case_table[usecase->id],
2030 out->usecase, use_case_table[out->usecase]);
2031 select_devices(adev, usecase->id);
2032 }
2033 }
2034
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002035 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002036 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002037 return ret;
2038}
2039
2040int start_output_stream(struct stream_out *out)
2041{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 struct audio_usecase *uc_info;
2044 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002045 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046
Eric Laurent994a6932013-07-17 11:51:42 -07002047 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002048 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002049
2050 if (out->card_status == CARD_STATUS_OFFLINE ||
2051 adev->card_status == CARD_STATUS_OFFLINE) {
2052 ALOGW("out->card_status or adev->card_status offline, try again");
2053 ret = -EAGAIN;
2054 goto error_config;
2055 }
2056
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002057 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2058 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002059 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002060 a2dp_combo = true;
2061 } else {
2062 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2063 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2064 ret = -EAGAIN;
2065 goto error_config;
2066 }
2067 }
2068 }
2069 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002070 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 if (out->pcm_device_id < 0) {
2072 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2073 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002074 ret = -EINVAL;
2075 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 }
2077
2078 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2079 uc_info->id = out->usecase;
2080 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002081 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002082 uc_info->devices = out->devices;
2083 uc_info->in_snd_device = SND_DEVICE_NONE;
2084 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085
Eric Laurent07eeafd2013-10-06 12:52:49 -07002086 /* This must be called before adding this usecase to the list */
2087 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2088 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002089 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2090 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2091 /* USB backend is not reopened immediately.
2092 This is eventually done as part of select_devices */
2093 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002094
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002095 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096
Wei Wangf4837d52017-11-21 14:51:20 -08002097 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002098 audio_extn_perf_lock_acquire();
2099
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002100 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2101 (!audio_extn_a2dp_is_ready())) {
2102 if (!a2dp_combo) {
2103 check_a2dp_restore_l(adev, out, false);
2104 } else {
2105 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002106 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2107 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2108 else
2109 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002110 select_devices(adev, out->usecase);
2111 out->devices = dev;
2112 }
2113 } else {
2114 select_devices(adev, out->usecase);
2115 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002116
Eric Laurent0499d4f2014-08-25 22:39:29 -05002117 audio_extn_extspk_update(adev->extspk);
2118
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002119 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2120 voice_set_device_mute_flag(adev, true);
2121
Andy Hung31aca912014-03-20 17:14:59 -07002122 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002123 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002124 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2125 out->pcm = NULL;
2126 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2127 COMPRESS_IN, &out->compr_config);
2128 if (out->compr && !is_compress_ready(out->compr)) {
2129 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2130 compress_close(out->compr);
2131 out->compr = NULL;
2132 ret = -EIO;
2133 goto error_open;
2134 }
2135 if (out->offload_callback)
2136 compress_nonblock(out->compr, out->non_blocking);
2137
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002138 if (adev->visualizer_start_output != NULL) {
2139 int capture_device_id =
2140 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2141 PCM_CAPTURE);
2142 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2143 adev->snd_card, capture_device_id);
2144 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002145 if (adev->offload_effects_start_output != NULL)
2146 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2147 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002148 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002149 ALOGE("%s: pcm stream not ready", __func__);
2150 goto error_open;
2151 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002152 ret = pcm_start(out->pcm);
2153 if (ret < 0) {
2154 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2155 goto error_open;
2156 }
2157 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002158 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002159 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002160
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002161 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2162 flags |= PCM_MMAP | PCM_NOIRQ;
2163 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002164 } else if (out->realtime) {
2165 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002166 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002167
2168 while (1) {
2169 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2170 flags, &out->config);
2171 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2172 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2173 if (out->pcm != NULL) {
2174 pcm_close(out->pcm);
2175 out->pcm = NULL;
2176 }
2177 if (pcm_open_retry_count-- == 0) {
2178 ret = -EIO;
2179 goto error_open;
2180 }
2181 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2182 continue;
2183 }
2184 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002186 ALOGV("%s: pcm_prepare", __func__);
2187 if (pcm_is_ready(out->pcm)) {
2188 ret = pcm_prepare(out->pcm);
2189 if (ret < 0) {
2190 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2191 pcm_close(out->pcm);
2192 out->pcm = NULL;
2193 goto error_open;
2194 }
2195 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002196 if (out->realtime) {
2197 ret = pcm_start(out->pcm);
2198 if (ret < 0) {
2199 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2200 pcm_close(out->pcm);
2201 out->pcm = NULL;
2202 goto error_open;
2203 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002204 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002205 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002206 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002207 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002208 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002209 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002210
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002211 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2212 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2213 audio_low_latency_hint_start();
2214 }
2215
vivek mehtae59cfb22017-06-16 15:57:11 -07002216 // consider a scenario where on pause lower layers are tear down.
2217 // so on resume, swap mixer control need to be sent only when
2218 // backend is active, hence rather than sending from enable device
2219 // sending it from start of streamtream
2220
2221 platform_set_swap_channels(adev, true);
2222
Eric Laurent994a6932013-07-17 11:51:42 -07002223 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002224 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002226 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002227 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002229error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002230 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231}
2232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233static int check_input_parameters(uint32_t sample_rate,
2234 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002235 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002237 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2238 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002239 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2240 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002241 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2242 return -EINVAL;
2243 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244
Eric Laurent74b55762017-07-09 17:04:53 -07002245 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2246 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002247 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002248 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002249 return -EINVAL;
2250 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251
2252 switch (sample_rate) {
2253 case 8000:
2254 case 11025:
2255 case 12000:
2256 case 16000:
2257 case 22050:
2258 case 24000:
2259 case 32000:
2260 case 44100:
2261 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002262 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263 break;
2264 default:
vivek mehtadae44712015-07-27 14:13:18 -07002265 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266 return -EINVAL;
2267 }
2268
2269 return 0;
2270}
2271
Kevin Rocarda325aa22018-04-03 09:15:52 -07002272/** Add a value in a list if not already present.
2273 * @return true if value was successfully inserted or already present,
2274 * false if the list is full and does not contain the value.
2275 */
2276static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2277 for (size_t i = 0; i < list_length; i++) {
2278 if (list[i] == value) return true; // value is already present
2279 if (list[i] == 0) { // no values in this slot
2280 list[i] = value;
2281 return true; // value inserted
2282 }
2283 }
2284 return false; // could not insert value
2285}
2286
2287/** Add channel_mask in supported_channel_masks if not already present.
2288 * @return true if channel_mask was successfully inserted or already present,
2289 * false if supported_channel_masks is full and does not contain channel_mask.
2290 */
2291static void register_channel_mask(audio_channel_mask_t channel_mask,
2292 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2293 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2294 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2295}
2296
2297/** Add format in supported_formats if not already present.
2298 * @return true if format was successfully inserted or already present,
2299 * false if supported_formats is full and does not contain format.
2300 */
2301static void register_format(audio_format_t format,
2302 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2303 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2304 "%s: stream can not declare supporting its format %x", __func__, format);
2305}
2306/** Add sample_rate in supported_sample_rates if not already present.
2307 * @return true if sample_rate was successfully inserted or already present,
2308 * false if supported_sample_rates is full and does not contain sample_rate.
2309 */
2310static void register_sample_rate(uint32_t sample_rate,
2311 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2312 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2313 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2314}
2315
vivek mehtaa68fea62017-06-08 19:04:02 -07002316static size_t get_stream_buffer_size(size_t duration_ms,
2317 uint32_t sample_rate,
2318 audio_format_t format,
2319 int channel_count,
2320 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321{
2322 size_t size = 0;
2323
vivek mehtaa68fea62017-06-08 19:04:02 -07002324 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002325 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002326 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002327
2328 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329
Glenn Kasten4f993392014-05-14 07:30:48 -07002330 /* make sure the size is multiple of 32 bytes
2331 * At 48 kHz mono 16-bit PCM:
2332 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2333 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2334 */
2335 size += 0x1f;
2336 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002337
2338 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002339}
2340
2341static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2342{
2343 struct stream_out *out = (struct stream_out *)stream;
2344
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002345 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002348static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349{
2350 return -ENOSYS;
2351}
2352
2353static size_t out_get_buffer_size(const struct audio_stream *stream)
2354{
2355 struct stream_out *out = (struct stream_out *)stream;
2356
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2358 return out->compr_config.fragment_size;
2359 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002360 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002361 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362}
2363
2364static uint32_t out_get_channels(const struct audio_stream *stream)
2365{
2366 struct stream_out *out = (struct stream_out *)stream;
2367
2368 return out->channel_mask;
2369}
2370
2371static audio_format_t out_get_format(const struct audio_stream *stream)
2372{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 struct stream_out *out = (struct stream_out *)stream;
2374
2375 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376}
2377
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002378static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379{
2380 return -ENOSYS;
2381}
2382
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002383/* must be called with out->lock locked */
2384static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385{
2386 struct stream_out *out = (struct stream_out *)stream;
2387 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002388 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002391 if (adev->adm_deregister_stream)
2392 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002393 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2396 if (out->pcm) {
2397 pcm_close(out->pcm);
2398 out->pcm = NULL;
2399 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002400 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002401 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002402 out->playback_started = false;
2403 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 } else {
2405 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002406 out->gapless_mdata.encoder_delay = 0;
2407 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002408 if (out->compr != NULL) {
2409 compress_close(out->compr);
2410 out->compr = NULL;
2411 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002412 }
Phil Burkbc991042017-02-24 08:06:44 -08002413 if (do_stop) {
2414 stop_output_stream(out);
2415 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002416 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002418 return 0;
2419}
2420
2421static int out_standby(struct audio_stream *stream)
2422{
2423 struct stream_out *out = (struct stream_out *)stream;
2424
2425 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2426 out->usecase, use_case_table[out->usecase]);
2427
2428 lock_output_stream(out);
2429 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002431 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432 return 0;
2433}
2434
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002435static int out_on_error(struct audio_stream *stream)
2436{
2437 struct stream_out *out = (struct stream_out *)stream;
2438 struct audio_device *adev = out->dev;
2439 bool do_standby = false;
2440
2441 lock_output_stream(out);
2442 if (!out->standby) {
2443 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2444 stop_compressed_output_l(out);
2445 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2446 } else
2447 do_standby = true;
2448 }
2449 pthread_mutex_unlock(&out->lock);
2450
2451 if (do_standby)
2452 return out_standby(&out->stream.common);
2453
2454 return 0;
2455}
2456
Andy Hung7401c7c2016-09-21 12:41:21 -07002457static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458{
Andy Hung7401c7c2016-09-21 12:41:21 -07002459 struct stream_out *out = (struct stream_out *)stream;
2460
2461 // We try to get the lock for consistency,
2462 // but it isn't necessary for these variables.
2463 // If we're not in standby, we may be blocked on a write.
2464 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2465 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2466 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2467
2468 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002469 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002470 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002471
2472 // dump error info
2473 (void)error_log_dump(
2474 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 return 0;
2477}
2478
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002479static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2480{
2481 int ret = 0;
2482 char value[32];
2483 struct compr_gapless_mdata tmp_mdata;
2484
2485 if (!out || !parms) {
2486 return -EINVAL;
2487 }
2488
2489 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2490 if (ret >= 0) {
2491 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2492 } else {
2493 return -EINVAL;
2494 }
2495
2496 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2497 if (ret >= 0) {
2498 tmp_mdata.encoder_padding = atoi(value);
2499 } else {
2500 return -EINVAL;
2501 }
2502
2503 out->gapless_mdata = tmp_mdata;
2504 out->send_new_metadata = 1;
2505 ALOGV("%s new encoder delay %u and padding %u", __func__,
2506 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2507
2508 return 0;
2509}
2510
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002511static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2512{
2513 return out == adev->primary_output || out == adev->voice_tx_output;
2514}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002515
Kevin Rocard1e02c882017-08-09 15:26:07 -07002516static int get_alive_usb_card(struct str_parms* parms) {
2517 int card;
2518 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2519 !audio_extn_usb_alive(card)) {
2520 return card;
2521 }
2522 return -ENODEV;
2523}
2524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002525static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2526{
2527 struct stream_out *out = (struct stream_out *)stream;
2528 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002529 struct audio_usecase *usecase;
2530 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 struct str_parms *parms;
2532 char value[32];
2533 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002534 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002535 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002536 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537
Eric Laurent2e140aa2016-06-30 17:14:46 -07002538 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002539 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 parms = str_parms_create_str(kvpairs);
2541 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2542 if (ret >= 0) {
2543 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002544
Eric Laurenta1478072015-09-21 17:21:52 -07002545 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002546
2547 // The usb driver needs to be closed after usb device disconnection
2548 // otherwise audio is no longer played on the new usb devices.
2549 // By forcing the stream in standby, the usb stack refcount drops to 0
2550 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002551 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002552 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002553 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2554 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2555 out_standby_l(&out->stream.common);
2556 }
2557 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002558 }
2559
Eric Laurent150dbfe2013-02-27 14:31:02 -08002560 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002562 /*
2563 * When HDMI cable is unplugged the music playback is paused and
2564 * the policy manager sends routing=0. But the audioflinger
2565 * continues to write data until standby time (3sec).
2566 * As the HDMI core is turned off, the write gets blocked.
2567 * Avoid this by routing audio to speaker until standby.
2568 */
2569 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2570 val == AUDIO_DEVICE_NONE) {
2571 val = AUDIO_DEVICE_OUT_SPEAKER;
2572 }
2573
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002574 /*
2575 * When A2DP is disconnected the
2576 * music playback is paused and the policy manager sends routing=0
2577 * But the audioflingercontinues to write data until standby time
2578 * (3sec). As BT is turned off, the write gets blocked.
2579 * Avoid this by routing audio to speaker until standby.
2580 */
2581 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2582 (val == AUDIO_DEVICE_NONE) &&
2583 !audio_extn_a2dp_is_ready()) {
2584 val = AUDIO_DEVICE_OUT_SPEAKER;
2585 }
2586
2587 /* To avoid a2dp to sco overlapping / BT device improper state
2588 * check with BT lib about a2dp streaming support before routing
2589 */
2590 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2591 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002592 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002593 //combo usecase just by pass a2dp
2594 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2595 bypass_a2dp = true;
2596 } else {
2597 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2598 /* update device to a2dp and don't route as BT returned error
2599 * However it is still possible a2dp routing called because
2600 * of current active device disconnection (like wired headset)
2601 */
2602 out->devices = val;
2603 pthread_mutex_unlock(&out->lock);
2604 pthread_mutex_unlock(&adev->lock);
2605 status = -ENOSYS;
2606 goto routing_fail;
2607 }
2608 }
2609 }
2610
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002611 audio_devices_t new_dev = val;
2612
2613 // Workaround: If routing to an non existing usb device, fail gracefully
2614 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002615 int card;
2616 if (audio_is_usb_out_device(new_dev) &&
2617 (card = get_alive_usb_card(parms)) >= 0) {
2618
2619 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002620 pthread_mutex_unlock(&adev->lock);
2621 pthread_mutex_unlock(&out->lock);
2622 status = -ENOSYS;
2623 goto routing_fail;
2624 }
2625
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002626 /*
2627 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002628 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002629 * the select_devices(). But how do we undo this?
2630 *
2631 * For example, music playback is active on headset (deep-buffer usecase)
2632 * and if we go to ringtones and select a ringtone, low-latency usecase
2633 * will be started on headset+speaker. As we can't enable headset+speaker
2634 * and headset devices at the same time, select_devices() switches the music
2635 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2636 * So when the ringtone playback is completed, how do we undo the same?
2637 *
2638 * We are relying on the out_set_parameters() call on deep-buffer output,
2639 * once the ringtone playback is ended.
2640 * NOTE: We should not check if the current devices are same as new devices.
2641 * Because select_devices() must be called to switch back the music
2642 * playback to headset.
2643 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002644 if (new_dev != AUDIO_DEVICE_NONE) {
2645 bool same_dev = out->devices == new_dev;
2646 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002647
Eric Laurenta7657192014-10-09 21:09:33 -07002648 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002649 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002650 if (adev->mode == AUDIO_MODE_IN_CALL) {
2651 adev->current_call_output = out;
2652 ret = voice_start_call(adev);
2653 }
2654 } else {
2655 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002656 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002657 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002658 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002659
2660 if (!out->standby) {
2661 if (!same_dev) {
2662 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002663 // inform adm before actual routing to prevent glitches.
2664 if (adev->adm_on_routing_change) {
2665 adev->adm_on_routing_change(adev->adm_data,
2666 out->handle);
2667 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002668 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002669 if (!bypass_a2dp) {
2670 select_devices(adev, out->usecase);
2671 } else {
juyuchen9baad392018-06-05 19:02:10 +08002672 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2673 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2674 else
2675 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002676 select_devices(adev, out->usecase);
2677 out->devices = new_dev;
2678 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002679 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002680
2681 // on device switch force swap, lower functions will make sure
2682 // to check if swap is allowed or not.
2683
2684 if (!same_dev)
2685 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002686
2687 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2688 out->a2dp_compress_mute &&
2689 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2690 pthread_mutex_lock(&out->compr_mute_lock);
2691 out->a2dp_compress_mute = false;
2692 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2693 pthread_mutex_unlock(&out->compr_mute_lock);
2694 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002695 }
2696
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002697 }
2698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002700 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002701
2702 /*handles device and call state changes*/
2703 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002705 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002706
2707 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2708 parse_compress_metadata(out, parms);
2709 }
2710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002712 ALOGV("%s: exit: code(%d)", __func__, status);
2713 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714}
2715
Haynes Mathew George569b7482017-05-08 14:44:27 -07002716static bool stream_get_parameter_channels(struct str_parms *query,
2717 struct str_parms *reply,
2718 audio_channel_mask_t *supported_channel_masks) {
2719 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002720 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002722 size_t i, j;
2723
2724 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2725 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 value[0] = '\0';
2727 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002728 while (supported_channel_masks[i] != 0) {
2729 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2730 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 if (!first) {
2732 strcat(value, "|");
2733 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002734 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 first = false;
2736 break;
2737 }
2738 }
2739 i++;
2740 }
2741 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002742 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002743 return ret >= 0;
2744}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002745
Haynes Mathew George569b7482017-05-08 14:44:27 -07002746static bool stream_get_parameter_formats(struct str_parms *query,
2747 struct str_parms *reply,
2748 audio_format_t *supported_formats) {
2749 int ret = -1;
2750 char value[256];
2751 int i;
2752
2753 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2754 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002755 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002756 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002757 case AUDIO_FORMAT_PCM_16_BIT:
2758 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2759 break;
2760 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2761 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2762 break;
2763 case AUDIO_FORMAT_PCM_32_BIT:
2764 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2765 break;
2766 default:
2767 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002768 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002769 break;
2770 }
2771 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002772 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002773 return ret >= 0;
2774}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002775
Haynes Mathew George569b7482017-05-08 14:44:27 -07002776static bool stream_get_parameter_rates(struct str_parms *query,
2777 struct str_parms *reply,
2778 uint32_t *supported_sample_rates) {
2779
2780 int i;
2781 char value[256];
2782 int ret = -1;
2783 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2784 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002785 value[0] = '\0';
2786 i=0;
2787 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002788 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002789 int avail = sizeof(value) - cursor;
2790 ret = snprintf(value + cursor, avail, "%s%d",
2791 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002792 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002793 if (ret < 0 || ret >= avail) {
2794 // if cursor is at the last element of the array
2795 // overwrite with \0 is duplicate work as
2796 // snprintf already put a \0 in place.
2797 // else
2798 // we had space to write the '|' at value[cursor]
2799 // (which will be overwritten) or no space to fill
2800 // the first element (=> cursor == 0)
2801 value[cursor] = '\0';
2802 break;
2803 }
2804 cursor += ret;
2805 ++i;
2806 }
2807 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2808 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002809 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002810 return ret >= 0;
2811}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002812
Haynes Mathew George569b7482017-05-08 14:44:27 -07002813static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2814{
2815 struct stream_out *out = (struct stream_out *)stream;
2816 struct str_parms *query = str_parms_create_str(keys);
2817 char *str;
2818 struct str_parms *reply = str_parms_create();
2819 bool replied = false;
2820 ALOGV("%s: enter: keys - %s", __func__, keys);
2821
2822 replied |= stream_get_parameter_channels(query, reply,
2823 &out->supported_channel_masks[0]);
2824 replied |= stream_get_parameter_formats(query, reply,
2825 &out->supported_formats[0]);
2826 replied |= stream_get_parameter_rates(query, reply,
2827 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002828 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 str = str_parms_to_str(reply);
2830 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002831 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 }
2833 str_parms_destroy(query);
2834 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002835 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 return str;
2837}
2838
2839static uint32_t out_get_latency(const struct audio_stream_out *stream)
2840{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002841 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002843 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2846 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002847 else if ((out->realtime) ||
2848 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002849 // since the buffer won't be filled up faster than realtime,
2850 // return a smaller number
2851 period_ms = (out->af_period_multiplier * out->config.period_size *
2852 1000) / (out->config.rate);
2853 hw_delay = platform_render_latency(out->usecase)/1000;
2854 return period_ms + hw_delay;
2855 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002857 latency = (out->config.period_count * out->config.period_size * 1000) /
2858 (out->config.rate);
2859
2860 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2861 latency += audio_extn_a2dp_get_encoder_latency();
2862
2863 return latency;
2864}
2865
2866static int set_compr_volume(struct audio_stream_out *stream, float left,
2867 float right)
2868{
2869 struct stream_out *out = (struct stream_out *)stream;
2870 int volume[2];
2871 char mixer_ctl_name[128];
2872 struct audio_device *adev = out->dev;
2873 struct mixer_ctl *ctl;
2874 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2875 PCM_PLAYBACK);
2876
2877 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2878 "Compress Playback %d Volume", pcm_device_id);
2879 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2880 if (!ctl) {
2881 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2882 __func__, mixer_ctl_name);
2883 return -EINVAL;
2884 }
2885 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2886 __func__, mixer_ctl_name, left, right);
2887 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2888 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2889 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2890
2891 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892}
2893
2894static int out_set_volume(struct audio_stream_out *stream, float left,
2895 float right)
2896{
Eric Laurenta9024de2013-04-04 09:19:12 -07002897 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002898 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002900 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002901 /* only take left channel into account: the API is for stereo anyway */
2902 out->muted = (left == 0.0f);
2903 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002905 pthread_mutex_lock(&out->compr_mute_lock);
2906 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2907 if (!out->a2dp_compress_mute)
2908 ret = set_compr_volume(stream, left, right);
2909 out->volume_l = left;
2910 out->volume_r = right;
2911 pthread_mutex_unlock(&out->compr_mute_lock);
2912 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002913 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002914 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2915 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2916 if (!out->standby) {
2917 // if in standby, cached volume will be sent after stream is opened
2918 audio_extn_utils_send_app_type_gain(out->dev,
2919 out->app_type_cfg.app_type,
2920 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002921 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002922 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002923 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 return -ENOSYS;
2926}
2927
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002928// note: this call is safe only if the stream_cb is
2929// removed first in close_output_stream (as is done now).
2930static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2931{
2932 if (!stream || !parms)
2933 return;
2934
2935 struct stream_out *out = (struct stream_out *)stream;
2936 struct audio_device *adev = out->dev;
2937
2938 card_status_t status;
2939 int card;
2940 if (parse_snd_card_status(parms, &card, &status) < 0)
2941 return;
2942
2943 pthread_mutex_lock(&adev->lock);
2944 bool valid_cb = (card == adev->snd_card);
2945 pthread_mutex_unlock(&adev->lock);
2946
2947 if (!valid_cb)
2948 return;
2949
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002950 lock_output_stream(out);
2951 if (out->card_status != status)
2952 out->card_status = status;
2953 pthread_mutex_unlock(&out->lock);
2954
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002955 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2956 use_case_table[out->usecase],
2957 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2958
2959 if (status == CARD_STATUS_OFFLINE)
2960 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002961
2962 return;
2963}
2964
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002965#ifdef NO_AUDIO_OUT
2966static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002967 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002968{
2969 struct stream_out *out = (struct stream_out *)stream;
2970
2971 /* No Output device supported other than BT for playback.
2972 * Sleep for the amount of buffer duration
2973 */
Eric Laurenta1478072015-09-21 17:21:52 -07002974 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002975 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2976 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002977 out_get_sample_rate(&out->stream.common));
2978 pthread_mutex_unlock(&out->lock);
2979 return bytes;
2980}
2981#endif
2982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2984 size_t bytes)
2985{
2986 struct stream_out *out = (struct stream_out *)stream;
2987 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002988 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002989 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990
Eric Laurenta1478072015-09-21 17:21:52 -07002991 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002992 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002993 const size_t frame_size = audio_stream_out_frame_size(stream);
2994 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002995
Eric Laurent0e46adf2016-12-16 12:49:24 -08002996 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2997 error_code = ERROR_CODE_WRITE;
2998 goto exit;
2999 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003000
3001 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3002 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003003 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003004 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3005 ret = -EIO;
3006 goto exit;
3007 }
3008 }
3009 }
3010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003012 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003013 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003015
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003016 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003018 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003019 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 goto exit;
3021 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003022
vivek mehta40125092017-08-21 18:48:51 -07003023 // after standby always force set last known cal step
3024 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3025 ALOGD("%s: retry previous failed cal level set", __func__);
3026 send_gain_dep_calibration_l();
3027 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003031 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003032 if (out->send_new_metadata) {
3033 ALOGVV("send new gapless metadata");
3034 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3035 out->send_new_metadata = 0;
3036 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003037 unsigned int avail;
3038 struct timespec tstamp;
3039 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3040 /* Do not limit write size if the available frames count is unknown */
3041 if (ret != 0) {
3042 avail = bytes;
3043 }
3044 if (avail == 0) {
3045 ret = 0;
3046 } else {
3047 if (avail > bytes) {
3048 avail = bytes;
3049 }
3050 ret = compress_write(out->compr, buffer, avail);
3051 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3052 __func__, avail, ret);
3053 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003054
Eric Laurent6e895242013-09-05 16:10:57 -07003055 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3057 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003058 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 compress_start(out->compr);
3060 out->playback_started = 1;
3061 out->offload_state = OFFLOAD_STATE_PLAYING;
3062 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003063 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003064 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003065 } else {
3066 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003067 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003069 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 return ret;
3071 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003072 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003074 size_t bytes_to_write = bytes;
3075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003076 if (out->muted)
3077 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003078 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003079 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003080 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3081 int16_t *src = (int16_t *)buffer;
3082 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003083
Eric Laurentad2dde92017-09-20 18:27:31 -07003084 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3085 out->format != AUDIO_FORMAT_PCM_16_BIT,
3086 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003087
Eric Laurentad2dde92017-09-20 18:27:31 -07003088 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3089 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3090 }
3091 bytes_to_write /= 2;
3092 }
3093 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3094
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003095 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003096 request_out_focus(out, ns);
3097
3098 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3099 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003100 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003101 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003102 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003103
Haynes Mathew George03c40102016-01-29 17:57:48 -08003104 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003105 } else {
3106 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 }
3109
3110exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003111 // For PCM we always consume the buffer and return #bytes regardless of ret.
3112 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003113 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003114 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003115 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003116
Andy Hung7401c7c2016-09-21 12:41:21 -07003117 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003118 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003119 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3120 ALOGE_IF(out->pcm != NULL,
3121 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003122 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003123 // usleep not guaranteed for values over 1 second but we don't limit here.
3124 }
3125 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 pthread_mutex_unlock(&out->lock);
3128
3129 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003130 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003131 if (sleeptime_us != 0)
3132 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 }
3134 return bytes;
3135}
3136
3137static int out_get_render_position(const struct audio_stream_out *stream,
3138 uint32_t *dsp_frames)
3139{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 struct stream_out *out = (struct stream_out *)stream;
3141 *dsp_frames = 0;
3142 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003143 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003145 unsigned long frames = 0;
3146 // TODO: check return value
3147 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3148 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003149 ALOGVV("%s rendered frames %d sample_rate %d",
3150 __func__, *dsp_frames, out->sample_rate);
3151 }
3152 pthread_mutex_unlock(&out->lock);
3153 return 0;
3154 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003155 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156}
3157
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003158static int out_add_audio_effect(const struct audio_stream *stream __unused,
3159 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003160{
3161 return 0;
3162}
3163
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003164static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3165 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166{
3167 return 0;
3168}
3169
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003170static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3171 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003173 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174}
3175
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003176static int out_get_presentation_position(const struct audio_stream_out *stream,
3177 uint64_t *frames, struct timespec *timestamp)
3178{
3179 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003180 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003181 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003182
Eric Laurenta1478072015-09-21 17:21:52 -07003183 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003184
Eric Laurent949a0892013-09-20 09:20:13 -07003185 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3186 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003187 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003188 compress_get_tstamp(out->compr, &dsp_frames,
3189 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003190 // Adjustment accounts for A2DP encoder latency with offload usecases
3191 // Note: Encoder latency is returned in ms.
3192 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3193 unsigned long offset =
3194 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3195 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3196 }
Eric Laurent949a0892013-09-20 09:20:13 -07003197 ALOGVV("%s rendered frames %ld sample_rate %d",
3198 __func__, dsp_frames, out->sample_rate);
3199 *frames = dsp_frames;
3200 ret = 0;
3201 /* this is the best we can do */
3202 clock_gettime(CLOCK_MONOTONIC, timestamp);
3203 }
3204 } else {
3205 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003206 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003207 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3208 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003209 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003210 // This adjustment accounts for buffering after app processor.
3211 // It is based on estimated DSP latency per use case, rather than exact.
3212 signed_frames -=
3213 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3214
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003215 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3216 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3217 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3218 signed_frames -=
3219 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3220 }
3221
Eric Laurent949a0892013-09-20 09:20:13 -07003222 // It would be unusual for this value to be negative, but check just in case ...
3223 if (signed_frames >= 0) {
3224 *frames = signed_frames;
3225 ret = 0;
3226 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003227 }
3228 }
3229 }
3230
3231 pthread_mutex_unlock(&out->lock);
3232
3233 return ret;
3234}
3235
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236static int out_set_callback(struct audio_stream_out *stream,
3237 stream_callback_t callback, void *cookie)
3238{
3239 struct stream_out *out = (struct stream_out *)stream;
3240
3241 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003242 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003243 out->offload_callback = callback;
3244 out->offload_cookie = cookie;
3245 pthread_mutex_unlock(&out->lock);
3246 return 0;
3247}
3248
3249static int out_pause(struct audio_stream_out* stream)
3250{
3251 struct stream_out *out = (struct stream_out *)stream;
3252 int status = -ENOSYS;
3253 ALOGV("%s", __func__);
3254 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003255 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3257 status = compress_pause(out->compr);
3258 out->offload_state = OFFLOAD_STATE_PAUSED;
3259 }
3260 pthread_mutex_unlock(&out->lock);
3261 }
3262 return status;
3263}
3264
3265static int out_resume(struct audio_stream_out* stream)
3266{
3267 struct stream_out *out = (struct stream_out *)stream;
3268 int status = -ENOSYS;
3269 ALOGV("%s", __func__);
3270 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3271 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003272 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003273 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3274 status = compress_resume(out->compr);
3275 out->offload_state = OFFLOAD_STATE_PLAYING;
3276 }
3277 pthread_mutex_unlock(&out->lock);
3278 }
3279 return status;
3280}
3281
3282static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3283{
3284 struct stream_out *out = (struct stream_out *)stream;
3285 int status = -ENOSYS;
3286 ALOGV("%s", __func__);
3287 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003288 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003289 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3290 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3291 else
3292 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3293 pthread_mutex_unlock(&out->lock);
3294 }
3295 return status;
3296}
3297
3298static int out_flush(struct audio_stream_out* stream)
3299{
3300 struct stream_out *out = (struct stream_out *)stream;
3301 ALOGV("%s", __func__);
3302 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003303 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003304 stop_compressed_output_l(out);
3305 pthread_mutex_unlock(&out->lock);
3306 return 0;
3307 }
3308 return -ENOSYS;
3309}
3310
Eric Laurent0e46adf2016-12-16 12:49:24 -08003311static int out_stop(const struct audio_stream_out* stream)
3312{
3313 struct stream_out *out = (struct stream_out *)stream;
3314 struct audio_device *adev = out->dev;
3315 int ret = -ENOSYS;
3316
3317 ALOGV("%s", __func__);
3318 pthread_mutex_lock(&adev->lock);
3319 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3320 out->playback_started && out->pcm != NULL) {
3321 pcm_stop(out->pcm);
3322 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003323 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003324 }
3325 pthread_mutex_unlock(&adev->lock);
3326 return ret;
3327}
3328
3329static int out_start(const struct audio_stream_out* stream)
3330{
3331 struct stream_out *out = (struct stream_out *)stream;
3332 struct audio_device *adev = out->dev;
3333 int ret = -ENOSYS;
3334
3335 ALOGV("%s", __func__);
3336 pthread_mutex_lock(&adev->lock);
3337 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3338 !out->playback_started && out->pcm != NULL) {
3339 ret = start_output_stream(out);
3340 if (ret == 0) {
3341 out->playback_started = true;
3342 }
3343 }
3344 pthread_mutex_unlock(&adev->lock);
3345 return ret;
3346}
3347
Phil Burkbc991042017-02-24 08:06:44 -08003348/*
3349 * Modify config->period_count based on min_size_frames
3350 */
3351static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3352{
3353 int periodCountRequested = (min_size_frames + config->period_size - 1)
3354 / config->period_size;
3355 int periodCount = MMAP_PERIOD_COUNT_MIN;
3356
3357 ALOGV("%s original config.period_size = %d config.period_count = %d",
3358 __func__, config->period_size, config->period_count);
3359
3360 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3361 periodCount *= 2;
3362 }
3363 config->period_count = periodCount;
3364
3365 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3366}
3367
Eric Laurent0e46adf2016-12-16 12:49:24 -08003368static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3369 int32_t min_size_frames,
3370 struct audio_mmap_buffer_info *info)
3371{
3372 struct stream_out *out = (struct stream_out *)stream;
3373 struct audio_device *adev = out->dev;
3374 int ret = 0;
3375 unsigned int offset1;
3376 unsigned int frames1;
3377 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003378 uint32_t mmap_size;
3379 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003380
3381 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003382 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003383 pthread_mutex_lock(&adev->lock);
3384
3385 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003386 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003387 ret = -EINVAL;
3388 goto exit;
3389 }
3390 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003391 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003392 ret = -ENOSYS;
3393 goto exit;
3394 }
3395 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3396 if (out->pcm_device_id < 0) {
3397 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3398 __func__, out->pcm_device_id, out->usecase);
3399 ret = -EINVAL;
3400 goto exit;
3401 }
Phil Burkbc991042017-02-24 08:06:44 -08003402
3403 adjust_mmap_period_count(&out->config, min_size_frames);
3404
Eric Laurent0e46adf2016-12-16 12:49:24 -08003405 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3406 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3407 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3408 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3409 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3410 step = "open";
3411 ret = -ENODEV;
3412 goto exit;
3413 }
3414 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3415 if (ret < 0) {
3416 step = "begin";
3417 goto exit;
3418 }
3419 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003420 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003421 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003422 ret = platform_get_mmap_data_fd(adev->platform,
3423 out->pcm_device_id, 0 /*playback*/,
3424 &info->shared_memory_fd,
3425 &mmap_size);
3426 if (ret < 0) {
3427 // Fall back to non exclusive mode
3428 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3429 } else {
3430 if (mmap_size < buffer_size) {
3431 step = "mmap";
3432 goto exit;
3433 }
3434 // FIXME: indicate exclusive mode support by returning a negative buffer size
3435 info->buffer_size_frames *= -1;
3436 }
3437 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003438
3439 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3440 if (ret < 0) {
3441 step = "commit";
3442 goto exit;
3443 }
Phil Burkbc991042017-02-24 08:06:44 -08003444
3445 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003446 ret = 0;
3447
3448 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3449 __func__, info->shared_memory_address, info->buffer_size_frames);
3450
3451exit:
3452 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003453 if (out->pcm == NULL) {
3454 ALOGE("%s: %s - %d", __func__, step, ret);
3455 } else {
3456 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003457 pcm_close(out->pcm);
3458 out->pcm = NULL;
3459 }
3460 }
3461 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003462 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003463 return ret;
3464}
3465
3466static int out_get_mmap_position(const struct audio_stream_out *stream,
3467 struct audio_mmap_position *position)
3468{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003469 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003470 struct stream_out *out = (struct stream_out *)stream;
3471 ALOGVV("%s", __func__);
3472 if (position == NULL) {
3473 return -EINVAL;
3474 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003475 lock_output_stream(out);
3476 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3477 out->pcm == NULL) {
3478 ret = -ENOSYS;
3479 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003480 }
3481
3482 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003483 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003484 if (ret < 0) {
3485 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003486 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003487 }
Andy Hungfc044e12017-03-20 09:24:22 -07003488 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003489exit:
3490 pthread_mutex_unlock(&out->lock);
3491 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003492}
3493
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495/** audio_stream_in implementation **/
3496static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3497{
3498 struct stream_in *in = (struct stream_in *)stream;
3499
3500 return in->config.rate;
3501}
3502
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003503static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504{
3505 return -ENOSYS;
3506}
3507
3508static size_t in_get_buffer_size(const struct audio_stream *stream)
3509{
3510 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003511 return in->config.period_size * in->af_period_multiplier *
3512 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513}
3514
3515static uint32_t in_get_channels(const struct audio_stream *stream)
3516{
3517 struct stream_in *in = (struct stream_in *)stream;
3518
3519 return in->channel_mask;
3520}
3521
vivek mehta4ed66e62016-04-15 23:33:34 -07003522static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523{
vivek mehta4ed66e62016-04-15 23:33:34 -07003524 struct stream_in *in = (struct stream_in *)stream;
3525 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526}
3527
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003528static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529{
3530 return -ENOSYS;
3531}
3532
3533static int in_standby(struct audio_stream *stream)
3534{
3535 struct stream_in *in = (struct stream_in *)stream;
3536 struct audio_device *adev = in->dev;
3537 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003538 bool do_stop = true;
3539
Eric Laurent994a6932013-07-17 11:51:42 -07003540 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003541
3542 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003543
3544 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003545 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003546 audio_extn_sound_trigger_stop_lab(in);
3547 in->standby = true;
3548 }
3549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003551 if (adev->adm_deregister_stream)
3552 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3553
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003554 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003556 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003557 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003558 in->capture_started = false;
3559 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003560 if (in->pcm) {
3561 pcm_close(in->pcm);
3562 in->pcm = NULL;
3563 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003564 adev->enable_voicerx = false;
3565 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003566 if (do_stop) {
3567 status = stop_input_stream(in);
3568 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003569 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 }
3571 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003572 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573 return status;
3574}
3575
Andy Hungd13f0d32017-06-12 13:58:37 -07003576static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577{
Andy Hungd13f0d32017-06-12 13:58:37 -07003578 struct stream_in *in = (struct stream_in *)stream;
3579
3580 // We try to get the lock for consistency,
3581 // but it isn't necessary for these variables.
3582 // If we're not in standby, we may be blocked on a read.
3583 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3584 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3585 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3586 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3587
3588 if (locked) {
3589 pthread_mutex_unlock(&in->lock);
3590 }
3591
3592 // dump error info
3593 (void)error_log_dump(
3594 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 return 0;
3596}
3597
3598static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3599{
3600 struct stream_in *in = (struct stream_in *)stream;
3601 struct audio_device *adev = in->dev;
3602 struct str_parms *parms;
3603 char *str;
3604 char value[32];
3605 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003606 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003607
Eric Laurent994a6932013-07-17 11:51:42 -07003608 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 parms = str_parms_create_str(kvpairs);
3610
3611 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3612
Eric Laurenta1478072015-09-21 17:21:52 -07003613 lock_input_stream(in);
3614
Eric Laurent150dbfe2013-02-27 14:31:02 -08003615 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 if (ret >= 0) {
3617 val = atoi(value);
3618 /* no audio source uses val == 0 */
3619 if ((in->source != val) && (val != 0)) {
3620 in->source = val;
3621 }
3622 }
3623
3624 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 if (ret >= 0) {
3627 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003628 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003629
3630 // Workaround: If routing to an non existing usb device, fail gracefully
3631 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003632 int card;
3633 if (audio_is_usb_in_device(val) &&
3634 (card = get_alive_usb_card(parms)) >= 0) {
3635
3636 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003637 status = -ENOSYS;
3638 } else {
3639
3640 in->device = val;
3641 /* If recording is in progress, change the tx device to new device */
3642 if (!in->standby) {
3643 ALOGV("update input routing change");
3644 // inform adm before actual routing to prevent glitches.
3645 if (adev->adm_on_routing_change) {
3646 adev->adm_on_routing_change(adev->adm_data,
3647 in->capture_handle);
3648 }
3649 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003650 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003651 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003652 }
3653 }
3654
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003655 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003656 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657
3658 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003659 ALOGV("%s: exit: status(%d)", __func__, status);
3660 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661}
3662
Haynes Mathew George569b7482017-05-08 14:44:27 -07003663static char* in_get_parameters(const struct audio_stream *stream,
3664 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003666 struct stream_in *in = (struct stream_in *)stream;
3667 struct str_parms *query = str_parms_create_str(keys);
3668 char *str;
3669 struct str_parms *reply = str_parms_create();
3670 bool replied = false;
3671
3672 ALOGV("%s: enter: keys - %s", __func__, keys);
3673 replied |= stream_get_parameter_channels(query, reply,
3674 &in->supported_channel_masks[0]);
3675 replied |= stream_get_parameter_formats(query, reply,
3676 &in->supported_formats[0]);
3677 replied |= stream_get_parameter_rates(query, reply,
3678 &in->supported_sample_rates[0]);
3679 if (replied) {
3680 str = str_parms_to_str(reply);
3681 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003682 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003683 }
3684 str_parms_destroy(query);
3685 str_parms_destroy(reply);
3686 ALOGV("%s: exit: returns - %s", __func__, str);
3687 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688}
3689
Eric Laurent51f3c662018-04-10 18:21:34 -07003690static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691{
Eric Laurent51f3c662018-04-10 18:21:34 -07003692 struct stream_in *in = (struct stream_in *)stream;
3693 char mixer_ctl_name[128];
3694 struct mixer_ctl *ctl;
3695 int ctl_value;
3696
3697 ALOGV("%s: gain %f", __func__, gain);
3698
3699 if (stream == NULL)
3700 return -EINVAL;
3701
3702 /* in_set_gain() only used to silence MMAP capture for now */
3703 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3704 return -ENOSYS;
3705
3706 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3707
3708 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3709 if (!ctl) {
3710 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3711 __func__, mixer_ctl_name);
3712 return -ENOSYS;
3713 }
3714
3715 if (gain < RECORD_GAIN_MIN)
3716 gain = RECORD_GAIN_MIN;
3717 else if (gain > RECORD_GAIN_MAX)
3718 gain = RECORD_GAIN_MAX;
3719 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3720
3721 mixer_ctl_set_value(ctl, 0, ctl_value);
3722 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723}
3724
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003725static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3726{
3727 if (!stream || !parms)
3728 return;
3729
3730 struct stream_in *in = (struct stream_in *)stream;
3731 struct audio_device *adev = in->dev;
3732
3733 card_status_t status;
3734 int card;
3735 if (parse_snd_card_status(parms, &card, &status) < 0)
3736 return;
3737
3738 pthread_mutex_lock(&adev->lock);
3739 bool valid_cb = (card == adev->snd_card);
3740 pthread_mutex_unlock(&adev->lock);
3741
3742 if (!valid_cb)
3743 return;
3744
3745 lock_input_stream(in);
3746 if (in->card_status != status)
3747 in->card_status = status;
3748 pthread_mutex_unlock(&in->lock);
3749
3750 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3751 use_case_table[in->usecase],
3752 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3753
3754 // a better solution would be to report error back to AF and let
3755 // it put the stream to standby
3756 if (status == CARD_STATUS_OFFLINE)
3757 in_standby(&in->stream.common);
3758
3759 return;
3760}
3761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3763 size_t bytes)
3764{
3765 struct stream_in *in = (struct stream_in *)stream;
3766 struct audio_device *adev = in->dev;
3767 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003768 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003769 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770
Eric Laurenta1478072015-09-21 17:21:52 -07003771 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003772 const size_t frame_size = audio_stream_in_frame_size(stream);
3773 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003774
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003775 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003776 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003777 /* Read from sound trigger HAL */
3778 audio_extn_sound_trigger_read(in, buffer, bytes);
3779 pthread_mutex_unlock(&in->lock);
3780 return bytes;
3781 }
3782
Eric Laurent0e46adf2016-12-16 12:49:24 -08003783 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3784 ret = -ENOSYS;
3785 goto exit;
3786 }
3787
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003789 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003791 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 goto exit;
3794 }
3795 in->standby = 0;
3796 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797
Andy Hungd13f0d32017-06-12 13:58:37 -07003798 // errors that occur here are read errors.
3799 error_code = ERROR_CODE_READ;
3800
Haynes Mathew George03c40102016-01-29 17:57:48 -08003801 //what's the duration requested by the client?
3802 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3803 in->config.rate;
3804 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003805
Haynes Mathew George03c40102016-01-29 17:57:48 -08003806 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003808 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003809 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003810 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003811 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003812 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003813 if (ret < 0) {
3814 ALOGE("Failed to read w/err %s", strerror(errno));
3815 ret = -errno;
3816 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003817 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3818 if (bytes % 4 == 0) {
3819 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3820 int_buf_stream = buffer;
3821 for (size_t itt=0; itt < bytes/4 ; itt++) {
3822 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003823 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003824 } else {
3825 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3826 ret = -EINVAL;
3827 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003828 }
3829 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830 }
3831
Haynes Mathew George03c40102016-01-29 17:57:48 -08003832 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003833
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003834 /*
3835 * Instead of writing zeroes here, we could trust the hardware
3836 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003837 * 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 -08003838 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003839 if (ret == 0 && adev->mic_muted &&
3840 !voice_is_in_call_rec_stream(in) &&
3841 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003842 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003843 in->frames_muted += frames;
3844 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845
3846exit:
3847 pthread_mutex_unlock(&in->lock);
3848
3849 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003850 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 in_standby(&in->stream.common);
3852 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003853 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003854 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003855 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003856 }
3857 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003858 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 }
3860 return bytes;
3861}
3862
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003863static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864{
3865 return 0;
3866}
3867
Andy Hung6ebe5962016-01-15 17:46:57 -08003868static int in_get_capture_position(const struct audio_stream_in *stream,
3869 int64_t *frames, int64_t *time)
3870{
3871 if (stream == NULL || frames == NULL || time == NULL) {
3872 return -EINVAL;
3873 }
3874 struct stream_in *in = (struct stream_in *)stream;
3875 int ret = -ENOSYS;
3876
3877 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003878 // note: ST sessions do not close the alsa pcm driver synchronously
3879 // on standby. Therefore, we may return an error even though the
3880 // pcm stream is still opened.
3881 if (in->standby) {
3882 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3883 "%s stream in standby but pcm not NULL for non ST session", __func__);
3884 goto exit;
3885 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003886 if (in->pcm) {
3887 struct timespec timestamp;
3888 unsigned int avail;
3889 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3890 *frames = in->frames_read + avail;
3891 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3892 ret = 0;
3893 }
3894 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003895exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003896 pthread_mutex_unlock(&in->lock);
3897 return ret;
3898}
3899
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003900static int add_remove_audio_effect(const struct audio_stream *stream,
3901 effect_handle_t effect,
3902 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003903{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003904 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003905 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003906 int status = 0;
3907 effect_descriptor_t desc;
3908
3909 status = (*effect)->get_descriptor(effect, &desc);
3910 if (status != 0)
3911 return status;
3912
Eric Laurenta1478072015-09-21 17:21:52 -07003913 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003914 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003915 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003916 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003917 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003918 in->enable_aec != enable &&
3919 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3920 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003921 if (!enable)
3922 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003923 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3924 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3925 adev->enable_voicerx = enable;
3926 struct audio_usecase *usecase;
3927 struct listnode *node;
3928 list_for_each(node, &adev->usecase_list) {
3929 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003930 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003931 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003932 }
3933 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003934 if (!in->standby)
3935 select_devices(in->dev, in->usecase);
3936 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003937 if (in->enable_ns != enable &&
3938 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3939 in->enable_ns = enable;
3940 if (!in->standby)
3941 select_devices(in->dev, in->usecase);
3942 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003943 pthread_mutex_unlock(&in->dev->lock);
3944 pthread_mutex_unlock(&in->lock);
3945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 return 0;
3947}
3948
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003949static int in_add_audio_effect(const struct audio_stream *stream,
3950 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951{
Eric Laurent994a6932013-07-17 11:51:42 -07003952 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003953 return add_remove_audio_effect(stream, effect, true);
3954}
3955
3956static int in_remove_audio_effect(const struct audio_stream *stream,
3957 effect_handle_t effect)
3958{
Eric Laurent994a6932013-07-17 11:51:42 -07003959 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003960 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961}
3962
Eric Laurent0e46adf2016-12-16 12:49:24 -08003963static int in_stop(const struct audio_stream_in* stream)
3964{
3965 struct stream_in *in = (struct stream_in *)stream;
3966 struct audio_device *adev = in->dev;
3967
3968 int ret = -ENOSYS;
3969 ALOGV("%s", __func__);
3970 pthread_mutex_lock(&adev->lock);
3971 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3972 in->capture_started && in->pcm != NULL) {
3973 pcm_stop(in->pcm);
3974 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003975 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003976 }
3977 pthread_mutex_unlock(&adev->lock);
3978 return ret;
3979}
3980
3981static int in_start(const struct audio_stream_in* stream)
3982{
3983 struct stream_in *in = (struct stream_in *)stream;
3984 struct audio_device *adev = in->dev;
3985 int ret = -ENOSYS;
3986
3987 ALOGV("%s in %p", __func__, in);
3988 pthread_mutex_lock(&adev->lock);
3989 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3990 !in->capture_started && in->pcm != NULL) {
3991 if (!in->capture_started) {
3992 ret = start_input_stream(in);
3993 if (ret == 0) {
3994 in->capture_started = true;
3995 }
3996 }
3997 }
3998 pthread_mutex_unlock(&adev->lock);
3999 return ret;
4000}
4001
4002static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4003 int32_t min_size_frames,
4004 struct audio_mmap_buffer_info *info)
4005{
4006 struct stream_in *in = (struct stream_in *)stream;
4007 struct audio_device *adev = in->dev;
4008 int ret = 0;
4009 unsigned int offset1;
4010 unsigned int frames1;
4011 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004012 uint32_t mmap_size;
4013 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004014
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004015 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004016 pthread_mutex_lock(&adev->lock);
4017 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004018
Eric Laurent0e46adf2016-12-16 12:49:24 -08004019 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004020 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004021 ret = -EINVAL;
4022 goto exit;
4023 }
4024 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004025 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004026 ALOGV("%s in %p", __func__, in);
4027 ret = -ENOSYS;
4028 goto exit;
4029 }
4030 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4031 if (in->pcm_device_id < 0) {
4032 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4033 __func__, in->pcm_device_id, in->usecase);
4034 ret = -EINVAL;
4035 goto exit;
4036 }
Phil Burkbc991042017-02-24 08:06:44 -08004037
4038 adjust_mmap_period_count(&in->config, min_size_frames);
4039
Eric Laurent0e46adf2016-12-16 12:49:24 -08004040 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4041 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4042 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4043 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4044 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4045 step = "open";
4046 ret = -ENODEV;
4047 goto exit;
4048 }
4049
4050 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4051 if (ret < 0) {
4052 step = "begin";
4053 goto exit;
4054 }
4055 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004056 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004057 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004058 ret = platform_get_mmap_data_fd(adev->platform,
4059 in->pcm_device_id, 1 /*capture*/,
4060 &info->shared_memory_fd,
4061 &mmap_size);
4062 if (ret < 0) {
4063 // Fall back to non exclusive mode
4064 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4065 } else {
4066 if (mmap_size < buffer_size) {
4067 step = "mmap";
4068 goto exit;
4069 }
4070 // FIXME: indicate exclusive mode support by returning a negative buffer size
4071 info->buffer_size_frames *= -1;
4072 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004073
Haynes Mathew George96483a22017-03-28 14:52:47 -07004074 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004075
4076 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4077 if (ret < 0) {
4078 step = "commit";
4079 goto exit;
4080 }
4081
Phil Burkbc991042017-02-24 08:06:44 -08004082 in->standby = false;
4083 ret = 0;
4084
Eric Laurent0e46adf2016-12-16 12:49:24 -08004085 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4086 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004087
4088exit:
4089 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004090 if (in->pcm == NULL) {
4091 ALOGE("%s: %s - %d", __func__, step, ret);
4092 } else {
4093 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004094 pcm_close(in->pcm);
4095 in->pcm = NULL;
4096 }
4097 }
4098 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004099 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004100 return ret;
4101}
4102
4103static int in_get_mmap_position(const struct audio_stream_in *stream,
4104 struct audio_mmap_position *position)
4105{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004106 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004107 struct stream_in *in = (struct stream_in *)stream;
4108 ALOGVV("%s", __func__);
4109 if (position == NULL) {
4110 return -EINVAL;
4111 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004112 lock_input_stream(in);
4113 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4114 in->pcm == NULL) {
4115 ret = -ENOSYS;
4116 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004117 }
4118 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004119 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004120 if (ret < 0) {
4121 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004122 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004123 }
Andy Hungfc044e12017-03-20 09:24:22 -07004124 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004125exit:
4126 pthread_mutex_unlock(&in->lock);
4127 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004128}
4129
jiabin8962a4d2018-03-19 18:21:24 -07004130static int in_get_active_microphones(const struct audio_stream_in *stream,
4131 struct audio_microphone_characteristic_t *mic_array,
4132 size_t *mic_count) {
4133 struct stream_in *in = (struct stream_in *)stream;
4134 struct audio_device *adev = in->dev;
4135 ALOGVV("%s", __func__);
4136
4137 lock_input_stream(in);
4138 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004139 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004140 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004141 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004142 pthread_mutex_unlock(&adev->lock);
4143 pthread_mutex_unlock(&in->lock);
4144
4145 return ret;
4146}
4147
4148static int adev_get_microphones(const struct audio_hw_device *dev,
4149 struct audio_microphone_characteristic_t *mic_array,
4150 size_t *mic_count) {
4151 struct audio_device *adev = (struct audio_device *)dev;
4152 ALOGVV("%s", __func__);
4153
4154 pthread_mutex_lock(&adev->lock);
4155 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4156 pthread_mutex_unlock(&adev->lock);
4157
4158 return ret;
4159}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161static int adev_open_output_stream(struct audio_hw_device *dev,
4162 audio_io_handle_t handle,
4163 audio_devices_t devices,
4164 audio_output_flags_t flags,
4165 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004166 struct audio_stream_out **stream_out,
4167 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168{
4169 struct audio_device *adev = (struct audio_device *)dev;
4170 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004171 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004172 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4173 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4174 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175
Andy Hungd9653bd2017-08-01 19:31:39 -07004176 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4177 return -ENOSYS;
4178 }
4179
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004180 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4181 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182 *stream_out = NULL;
4183 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4184
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004185 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187 if (devices == AUDIO_DEVICE_NONE)
4188 devices = AUDIO_DEVICE_OUT_SPEAKER;
4189
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190 out->flags = flags;
4191 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004192 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004193 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004194 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195
4196 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004197 if ((is_hdmi || is_usb_dev) &&
4198 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4199 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4200 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004201 audio_format_t req_format = config->format;
4202 audio_channel_mask_t req_channel_mask = config->channel_mask;
4203 uint32_t req_sample_rate = config->sample_rate;
4204
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004205 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004206 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004207 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004208 if (config->sample_rate == 0)
4209 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004210 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004211 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4212 if (config->format == AUDIO_FORMAT_DEFAULT)
4213 config->format = AUDIO_FORMAT_PCM_16_BIT;
4214 } else if (is_usb_dev) {
4215 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4216 &config->format,
4217 &out->supported_formats[0],
4218 MAX_SUPPORTED_FORMATS,
4219 &config->channel_mask,
4220 &out->supported_channel_masks[0],
4221 MAX_SUPPORTED_CHANNEL_MASKS,
4222 &config->sample_rate,
4223 &out->supported_sample_rates[0],
4224 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004225 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004226 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004227 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004228 if (ret != 0) {
4229 // For MMAP NO IRQ, allow conversions in ADSP
4230 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4231 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004232
Eric Laurentab805ee2018-03-30 12:20:38 -07004233 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4234 config->sample_rate = req_sample_rate;
4235 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4236 config->channel_mask = req_channel_mask;
4237 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4238 config->format = req_format;
4239 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004240
Haynes Mathew George569b7482017-05-08 14:44:27 -07004241 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004242 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004243 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004244 if (is_hdmi) {
4245 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4246 out->config = pcm_config_hdmi_multi;
4247 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4248 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4249 out->config = pcm_config_mmap_playback;
4250 out->stream.start = out_start;
4251 out->stream.stop = out_stop;
4252 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4253 out->stream.get_mmap_position = out_get_mmap_position;
4254 } else {
4255 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4256 out->config = pcm_config_hifi;
4257 }
4258
4259 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004260 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004261 if (is_hdmi) {
4262 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4263 audio_bytes_per_sample(out->format));
4264 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004265 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004266 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004267 pthread_mutex_lock(&adev->lock);
4268 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4269 pthread_mutex_unlock(&adev->lock);
4270
4271 // reject offload during card offline to allow
4272 // fallback to s/w paths
4273 if (offline) {
4274 ret = -ENODEV;
4275 goto error_open;
4276 }
4277
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004278 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4279 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4280 ALOGE("%s: Unsupported Offload information", __func__);
4281 ret = -EINVAL;
4282 goto error_open;
4283 }
4284 if (!is_supported_format(config->offload_info.format)) {
4285 ALOGE("%s: Unsupported audio format", __func__);
4286 ret = -EINVAL;
4287 goto error_open;
4288 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004289 out->sample_rate = config->offload_info.sample_rate;
4290 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4291 out->channel_mask = config->offload_info.channel_mask;
4292 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4293 out->channel_mask = config->channel_mask;
4294 else
4295 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4296
4297 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004298
4299 out->compr_config.codec = (struct snd_codec *)
4300 calloc(1, sizeof(struct snd_codec));
4301
4302 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004303
4304 out->stream.set_callback = out_set_callback;
4305 out->stream.pause = out_pause;
4306 out->stream.resume = out_resume;
4307 out->stream.drain = out_drain;
4308 out->stream.flush = out_flush;
4309
4310 out->compr_config.codec->id =
4311 get_snd_codec_id(config->offload_info.format);
4312 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4313 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004314 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004315 out->compr_config.codec->bit_rate =
4316 config->offload_info.bit_rate;
4317 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004318 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004319 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4320
4321 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4322 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004323
4324 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004325 create_offload_callback_thread(out);
4326 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4327 __func__, config->offload_info.version,
4328 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004329 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4330 switch (config->sample_rate) {
4331 case 0:
4332 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4333 break;
4334 case 8000:
4335 case 16000:
4336 case 48000:
4337 out->sample_rate = config->sample_rate;
4338 break;
4339 default:
4340 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4341 config->sample_rate);
4342 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4343 ret = -EINVAL;
4344 goto error_open;
4345 }
4346 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4347 switch (config->channel_mask) {
4348 case AUDIO_CHANNEL_NONE:
4349 case AUDIO_CHANNEL_OUT_STEREO:
4350 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4351 break;
4352 default:
4353 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4354 config->channel_mask);
4355 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4356 ret = -EINVAL;
4357 goto error_open;
4358 }
4359 switch (config->format) {
4360 case AUDIO_FORMAT_DEFAULT:
4361 case AUDIO_FORMAT_PCM_16_BIT:
4362 out->format = AUDIO_FORMAT_PCM_16_BIT;
4363 break;
4364 default:
4365 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4366 config->format);
4367 config->format = AUDIO_FORMAT_PCM_16_BIT;
4368 ret = -EINVAL;
4369 goto error_open;
4370 }
4371
4372 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004373 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004374 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004375 case 0:
4376 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4377 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004378 case 8000:
4379 case 16000:
4380 case 48000:
4381 out->sample_rate = config->sample_rate;
4382 break;
4383 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004384 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4385 config->sample_rate);
4386 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4387 ret = -EINVAL;
4388 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004389 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004390 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4391 switch (config->channel_mask) {
4392 case AUDIO_CHANNEL_NONE:
4393 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4394 break;
4395 case AUDIO_CHANNEL_OUT_STEREO:
4396 out->channel_mask = config->channel_mask;
4397 break;
4398 default:
4399 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4400 config->channel_mask);
4401 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4402 ret = -EINVAL;
4403 break;
4404 }
4405 switch (config->format) {
4406 case AUDIO_FORMAT_DEFAULT:
4407 out->format = AUDIO_FORMAT_PCM_16_BIT;
4408 break;
4409 case AUDIO_FORMAT_PCM_16_BIT:
4410 out->format = config->format;
4411 break;
4412 default:
4413 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4414 config->format);
4415 config->format = AUDIO_FORMAT_PCM_16_BIT;
4416 ret = -EINVAL;
4417 break;
4418 }
4419 if (ret != 0)
4420 goto error_open;
4421
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004422 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4423 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004424 out->config.rate = out->sample_rate;
4425 out->config.channels =
4426 audio_channel_count_from_out_mask(out->channel_mask);
4427 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004428 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004429 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4430 switch (config->sample_rate) {
4431 case 0:
4432 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4433 break;
4434 case 8000:
4435 case 16000:
4436 case 32000:
4437 case 48000:
4438 out->sample_rate = config->sample_rate;
4439 break;
4440 default:
4441 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4442 config->sample_rate);
4443 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4444 ret = -EINVAL;
4445 break;
4446 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004447 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004448 switch (config->channel_mask) {
4449 case AUDIO_CHANNEL_NONE:
4450 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4451 break;
4452 case AUDIO_CHANNEL_OUT_STEREO:
4453 out->channel_mask = config->channel_mask;
4454 break;
4455 default:
4456 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4457 config->channel_mask);
4458 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4459 ret = -EINVAL;
4460 break;
4461 }
4462 switch (config->format) {
4463 case AUDIO_FORMAT_DEFAULT:
4464 out->format = AUDIO_FORMAT_PCM_16_BIT;
4465 break;
4466 case AUDIO_FORMAT_PCM_16_BIT:
4467 out->format = config->format;
4468 break;
4469 default:
4470 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4471 config->format);
4472 config->format = AUDIO_FORMAT_PCM_16_BIT;
4473 ret = -EINVAL;
4474 break;
4475 }
4476 if (ret != 0)
4477 goto error_open;
4478
vivek mehtaa68fea62017-06-08 19:04:02 -07004479 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004480 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4481 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004482 out->config.rate = out->sample_rate;
4483 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004484 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004485 out->sample_rate,
4486 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004487 out->config.channels,
4488 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004489 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004490 out->config.period_size = buffer_size / frame_size;
4491 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4492 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004494 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004495 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4496 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004497 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004498 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4499 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004500 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004501 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004502 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004503 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004504 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004505 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4506 out->config = pcm_config_mmap_playback;
4507 out->stream.start = out_start;
4508 out->stream.stop = out_stop;
4509 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4510 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004511 } else {
4512 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4513 out->config = pcm_config_low_latency;
4514 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004515
4516 if (config->sample_rate == 0) {
4517 out->sample_rate = out->config.rate;
4518 } else {
4519 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004520 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004521 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4522 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4523 } else {
4524 out->channel_mask = config->channel_mask;
4525 }
4526 if (config->format == AUDIO_FORMAT_DEFAULT)
4527 out->format = audio_format_from_pcm_format(out->config.format);
4528 else if (!audio_is_linear_pcm(config->format)) {
4529 config->format = AUDIO_FORMAT_PCM_16_BIT;
4530 ret = -EINVAL;
4531 goto error_open;
4532 } else {
4533 out->format = config->format;
4534 }
4535
4536 out->config.rate = out->sample_rate;
4537 out->config.channels =
4538 audio_channel_count_from_out_mask(out->channel_mask);
4539 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4540 out->config.format = pcm_format_from_audio_format(out->format);
4541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004543
4544 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4545 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004546 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004547 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4548 __func__, config->sample_rate, config->format, config->channel_mask);
4549 config->sample_rate = out->sample_rate;
4550 config->format = out->format;
4551 config->channel_mask = out->channel_mask;
4552 ret = -EINVAL;
4553 goto error_open;
4554 }
4555
Andy Hung6fcba9c2014-03-18 11:53:32 -07004556 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4557 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004559 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004560 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004561 adev->primary_output = out;
4562 else {
4563 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004564 ret = -EEXIST;
4565 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004566 }
4567 }
4568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004569 /* Check if this usecase is already existing */
4570 pthread_mutex_lock(&adev->lock);
4571 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4572 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004574 ret = -EEXIST;
4575 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576 }
4577 pthread_mutex_unlock(&adev->lock);
4578
4579 out->stream.common.get_sample_rate = out_get_sample_rate;
4580 out->stream.common.set_sample_rate = out_set_sample_rate;
4581 out->stream.common.get_buffer_size = out_get_buffer_size;
4582 out->stream.common.get_channels = out_get_channels;
4583 out->stream.common.get_format = out_get_format;
4584 out->stream.common.set_format = out_set_format;
4585 out->stream.common.standby = out_standby;
4586 out->stream.common.dump = out_dump;
4587 out->stream.common.set_parameters = out_set_parameters;
4588 out->stream.common.get_parameters = out_get_parameters;
4589 out->stream.common.add_audio_effect = out_add_audio_effect;
4590 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4591 out->stream.get_latency = out_get_latency;
4592 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004593#ifdef NO_AUDIO_OUT
4594 out->stream.write = out_write_for_no_output;
4595#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004597#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 out->stream.get_render_position = out_get_render_position;
4599 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004600 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601
Eric Laurent0e46adf2016-12-16 12:49:24 -08004602 if (out->realtime)
4603 out->af_period_multiplier = af_period_multiplier;
4604 else
4605 out->af_period_multiplier = 1;
4606
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004608 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004609 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004610
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004611 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004612 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004613 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 config->format = out->stream.common.get_format(&out->stream.common);
4616 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4617 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4618
Kevin Rocarda325aa22018-04-03 09:15:52 -07004619 register_format(out->format, out->supported_formats);
4620 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4621 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4622
Andy Hunga452b0a2017-03-15 14:51:15 -07004623 out->error_log = error_log_create(
4624 ERROR_LOG_ENTRIES,
4625 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4626
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004627 /*
4628 By locking output stream before registering, we allow the callback
4629 to update stream's state only after stream's initial state is set to
4630 adev state.
4631 */
4632 lock_output_stream(out);
4633 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4634 pthread_mutex_lock(&adev->lock);
4635 out->card_status = adev->card_status;
4636 pthread_mutex_unlock(&adev->lock);
4637 pthread_mutex_unlock(&out->lock);
4638
vivek mehta4a824772017-06-08 19:05:49 -07004639 stream_app_type_cfg_init(&out->app_type_cfg);
4640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004642
Eric Laurent994a6932013-07-17 11:51:42 -07004643 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004645
4646error_open:
4647 free(out);
4648 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004649 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004650 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651}
4652
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004653static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 struct audio_stream_out *stream)
4655{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004656 struct stream_out *out = (struct stream_out *)stream;
4657 struct audio_device *adev = out->dev;
4658
Eric Laurent994a6932013-07-17 11:51:42 -07004659 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004660
4661 // must deregister from sndmonitor first to prevent races
4662 // between the callback and close_stream
4663 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004665 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4666 destroy_offload_callback_thread(out);
4667
4668 if (out->compr_config.codec != NULL)
4669 free(out->compr_config.codec);
4670 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004671
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004672 out->a2dp_compress_mute = false;
4673
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004674 if (adev->voice_tx_output == out)
4675 adev->voice_tx_output = NULL;
4676
Andy Hunga452b0a2017-03-15 14:51:15 -07004677 error_log_destroy(out->error_log);
4678 out->error_log = NULL;
4679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004680 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004681 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004682 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004684 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685}
4686
4687static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4688{
4689 struct audio_device *adev = (struct audio_device *)dev;
4690 struct str_parms *parms;
4691 char *str;
4692 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004693 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004695 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004696 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697
Joe Onorato188b6222016-03-01 11:02:27 -08004698 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004699
4700 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701
4702 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004703 status = voice_set_parameters(adev, parms);
4704 if (status != 0) {
4705 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706 }
4707
4708 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4709 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004710 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4712 adev->bluetooth_nrec = true;
4713 else
4714 adev->bluetooth_nrec = false;
4715 }
4716
4717 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4718 if (ret >= 0) {
4719 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4720 adev->screen_off = false;
4721 else
4722 adev->screen_off = true;
4723 }
4724
jasmine cha270b7762018-03-30 15:41:33 +08004725#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004726 ret = str_parms_get_int(parms, "rotation", &val);
4727 if (ret >= 0) {
4728 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004729 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004730 // FIXME: note that the code below assumes that the speakers are in the correct placement
4731 // relative to the user when the device is rotated 90deg from its default rotation. This
4732 // assumption is device-specific, not platform-specific like this code.
4733 case 270:
4734 reverse_speakers = true;
4735 break;
4736 case 0:
4737 case 90:
4738 case 180:
4739 break;
4740 default:
4741 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004742 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004743 }
Eric Laurent03f09432014-03-25 18:09:11 -07004744 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004745 // check and set swap
4746 // - check if orientation changed and speaker active
4747 // - set rotation and cache the rotation value
4748 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004749 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004750 }
jasmine cha270b7762018-03-30 15:41:33 +08004751#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004752
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004753 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4754 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004755 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004756 }
4757
David Linee3fe402017-03-13 10:00:42 -07004758 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4759 if (ret >= 0) {
4760 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004761 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004762 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4763 if (ret >= 0) {
4764 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004765 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004766 }
Eric Laurent99dab492017-06-17 15:19:08 -07004767 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004768 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4769 if (ret >= 0) {
4770 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004771 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004772 }
4773 }
4774 }
4775
4776 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4777 if (ret >= 0) {
4778 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004779 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004780 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4781 if (ret >= 0) {
4782 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004783 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004784 }
Eric Laurent99dab492017-06-17 15:19:08 -07004785 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004786 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4787 if (ret >= 0) {
4788 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004789 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004790 }
4791 }
4792 }
4793
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004794 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004795 audio_extn_ma_set_parameters(adev, parms);
4796
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004797 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4798 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004799 struct audio_usecase *usecase;
4800 struct listnode *node;
4801 list_for_each(node, &adev->usecase_list) {
4802 usecase = node_to_item(node, struct audio_usecase, list);
4803 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004804 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004805 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4806
4807 pthread_mutex_unlock(&adev->lock);
4808 lock_output_stream(usecase->stream.out);
4809 pthread_mutex_lock(&adev->lock);
4810 audio_extn_a2dp_set_handoff_mode(true);
4811 // force device switch to reconfigure encoder
4812 select_devices(adev, usecase->id);
4813 audio_extn_a2dp_set_handoff_mode(false);
4814 pthread_mutex_unlock(&usecase->stream.out->lock);
4815 break;
4816 }
4817 }
4818 }
4819
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004820done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004822 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004823 ALOGV("%s: exit with code(%d)", __func__, status);
4824 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004825}
4826
4827static char* adev_get_parameters(const struct audio_hw_device *dev,
4828 const char *keys)
4829{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004830 struct audio_device *adev = (struct audio_device *)dev;
4831 struct str_parms *reply = str_parms_create();
4832 struct str_parms *query = str_parms_create_str(keys);
4833 char *str;
4834
4835 pthread_mutex_lock(&adev->lock);
4836
4837 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004838 audio_extn_a2dp_get_parameters(query, reply);
4839
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004840 str = str_parms_to_str(reply);
4841 str_parms_destroy(query);
4842 str_parms_destroy(reply);
4843
4844 pthread_mutex_unlock(&adev->lock);
4845 ALOGV("%s: exit: returns - %s", __func__, str);
4846 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004847}
4848
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004849static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004850{
4851 return 0;
4852}
4853
Haynes Mathew George5191a852013-09-11 14:19:36 -07004854static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4855{
4856 int ret;
4857 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004858
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004859 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4860
Haynes Mathew George5191a852013-09-11 14:19:36 -07004861 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004862 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004863 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004864
Haynes Mathew George5191a852013-09-11 14:19:36 -07004865 return ret;
4866}
4867
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004868static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869{
4870 return -ENOSYS;
4871}
4872
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004873static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4874 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875{
4876 return -ENOSYS;
4877}
4878
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004879static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004880{
4881 return -ENOSYS;
4882}
4883
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004884static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885{
4886 return -ENOSYS;
4887}
4888
4889static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4890{
4891 struct audio_device *adev = (struct audio_device *)dev;
4892
4893 pthread_mutex_lock(&adev->lock);
4894 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004895 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004896 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004897 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4898 voice_is_in_call(adev)) {
4899 voice_stop_call(adev);
4900 adev->current_call_output = NULL;
4901 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 }
4903 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004904
4905 audio_extn_extspk_set_mode(adev->extspk, mode);
4906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907 return 0;
4908}
4909
4910static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4911{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004912 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004914
Eric Laurent2bafff12016-03-17 12:17:23 -07004915 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004916 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004917 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4918 ret = audio_extn_hfp_set_mic_mute(adev, state);
4919 } else {
4920 ret = voice_set_mic_mute(adev, state);
4921 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004922 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004923 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004924
4925 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004926}
4927
4928static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4929{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004930 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931 return 0;
4932}
4933
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004934static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004935 const struct audio_config *config)
4936{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004937 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938
Eric Laurent74b55762017-07-09 17:04:53 -07004939 /* Don't know if USB HIFI in this context so use true to be conservative */
4940 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4941 true /*is_usb_hifi */) != 0)
4942 return 0;
4943
vivek mehtaa68fea62017-06-08 19:04:02 -07004944 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4945 config->sample_rate, config->format,
4946 channel_count,
4947 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004948}
4949
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004950static bool adev_input_allow_hifi_record(struct audio_device *adev,
4951 audio_devices_t devices,
4952 audio_input_flags_t flags,
4953 audio_source_t source) {
4954 const bool allowed = true;
4955
4956 if (!audio_is_usb_in_device(devices))
4957 return !allowed;
4958
4959 switch (flags) {
4960 case AUDIO_INPUT_FLAG_NONE:
4961 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4962 break;
4963 default:
4964 return !allowed;
4965 }
4966
4967 switch (source) {
4968 case AUDIO_SOURCE_DEFAULT:
4969 case AUDIO_SOURCE_MIC:
4970 case AUDIO_SOURCE_UNPROCESSED:
4971 break;
4972 default:
4973 return !allowed;
4974 }
4975
4976 switch (adev->mode) {
4977 case 0:
4978 break;
4979 default:
4980 return !allowed;
4981 }
4982
4983 return allowed;
4984}
4985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004986static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004987 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 audio_devices_t devices,
4989 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004990 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004991 audio_input_flags_t flags,
4992 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004993 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994{
4995 struct audio_device *adev = (struct audio_device *)dev;
4996 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004997 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004998 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004999 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005000 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005001 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5002 devices,
5003 flags,
5004 source);
Eric Laurent74b55762017-07-09 17:04:53 -07005005 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005007
Andy Hungd9653bd2017-08-01 19:31:39 -07005008 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5009 return -ENOSYS;
5010 }
5011
Eric Laurent74b55762017-07-09 17:04:53 -07005012 if (!(is_usb_dev && may_use_hifi_record)) {
5013 if (config->sample_rate == 0)
5014 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5015 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5016 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5017 if (config->format == AUDIO_FORMAT_DEFAULT)
5018 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005019
Eric Laurent74b55762017-07-09 17:04:53 -07005020 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5021
5022 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5023 return -EINVAL;
5024 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005025
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005026 if (audio_extn_tfa_98xx_is_supported() &&
5027 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005028 return -EINVAL;
5029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005030 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5031
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005032 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005033 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005035 in->stream.common.get_sample_rate = in_get_sample_rate;
5036 in->stream.common.set_sample_rate = in_set_sample_rate;
5037 in->stream.common.get_buffer_size = in_get_buffer_size;
5038 in->stream.common.get_channels = in_get_channels;
5039 in->stream.common.get_format = in_get_format;
5040 in->stream.common.set_format = in_set_format;
5041 in->stream.common.standby = in_standby;
5042 in->stream.common.dump = in_dump;
5043 in->stream.common.set_parameters = in_set_parameters;
5044 in->stream.common.get_parameters = in_get_parameters;
5045 in->stream.common.add_audio_effect = in_add_audio_effect;
5046 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5047 in->stream.set_gain = in_set_gain;
5048 in->stream.read = in_read;
5049 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005050 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005051 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005052
5053 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005054 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005055 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005056 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005057 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005058 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005059
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005060 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5061 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5062 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5063 /* Force channel config requested to mono if incall
5064 record is being requested for only uplink/downlink */
5065 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5066 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5067 ret = -EINVAL;
5068 goto err_open;
5069 }
5070 }
5071
Haynes Mathew George569b7482017-05-08 14:44:27 -07005072 if (is_usb_dev && may_use_hifi_record) {
5073 /* HiFi record selects an appropriate format, channel, rate combo
5074 depending on sink capabilities*/
5075 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5076 &config->format,
5077 &in->supported_formats[0],
5078 MAX_SUPPORTED_FORMATS,
5079 &config->channel_mask,
5080 &in->supported_channel_masks[0],
5081 MAX_SUPPORTED_CHANNEL_MASKS,
5082 &config->sample_rate,
5083 &in->supported_sample_rates[0],
5084 MAX_SUPPORTED_SAMPLE_RATES);
5085 if (ret != 0) {
5086 ret = -EINVAL;
5087 goto err_open;
5088 }
Eric Laurent74b55762017-07-09 17:04:53 -07005089 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005090 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005091 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005092 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5093 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5094 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5095 bool ret_error = false;
5096 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5097 from HAL is 8_24
5098 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5099 8_24 return error indicating supported format is 8_24
5100 *> In case of any other source requesting 24 bit or float return error
5101 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005102
vivek mehta57ff9b52016-04-28 14:13:08 -07005103 on error flinger will retry with supported format passed
5104 */
5105 if (source != AUDIO_SOURCE_UNPROCESSED) {
5106 config->format = AUDIO_FORMAT_PCM_16_BIT;
5107 ret_error = true;
5108 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5109 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5110 ret_error = true;
5111 }
5112
5113 if (ret_error) {
5114 ret = -EINVAL;
5115 goto err_open;
5116 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005117 }
5118
vivek mehta57ff9b52016-04-28 14:13:08 -07005119 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005120 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005122 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005123 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5124 if (config->sample_rate == 0)
5125 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5126 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5127 config->sample_rate != 8000) {
5128 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5129 ret = -EINVAL;
5130 goto err_open;
5131 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005132
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005133 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5134 config->format = AUDIO_FORMAT_PCM_16_BIT;
5135 ret = -EINVAL;
5136 goto err_open;
5137 }
5138
5139 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5140 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005141 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005142 } else if (is_usb_dev && may_use_hifi_record) {
5143 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5144 in->config = pcm_config_audio_capture;
5145 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005146 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5147 config->sample_rate,
5148 config->format,
5149 channel_count,
5150 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005151 in->config.period_size = buffer_size / frame_size;
5152 in->config.rate = config->sample_rate;
5153 in->af_period_multiplier = 1;
5154 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005155 } else {
5156 in->usecase = USECASE_AUDIO_RECORD;
5157 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005158 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005159 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005160#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005161 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005162#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005163 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005164 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005165 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005166 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005167 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5168 config->sample_rate,
5169 config->format,
5170 channel_count,
5171 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005172 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005173 in->config.rate = config->sample_rate;
5174 in->af_period_multiplier = 1;
5175 } else {
5176 // period size is left untouched for rt mode playback
5177 in->config = pcm_config_audio_capture_rt;
5178 in->af_period_multiplier = af_period_multiplier;
5179 }
5180 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5181 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005182 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005183 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5184 in->config = pcm_config_mmap_capture;
5185 in->stream.start = in_start;
5186 in->stream.stop = in_stop;
5187 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5188 in->stream.get_mmap_position = in_get_mmap_position;
5189 in->af_period_multiplier = 1;
5190 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005191 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005192 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005193 (config->sample_rate == 8000 ||
5194 config->sample_rate == 16000 ||
5195 config->sample_rate == 32000 ||
5196 config->sample_rate == 48000) &&
5197 channel_count == 1) {
5198 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5199 in->config = pcm_config_audio_capture;
5200 frame_size = audio_stream_in_frame_size(&in->stream);
5201 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5202 config->sample_rate,
5203 config->format,
5204 channel_count, false /*is_low_latency*/);
5205 in->config.period_size = buffer_size / frame_size;
5206 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5207 in->config.rate = config->sample_rate;
5208 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005209 } else {
5210 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005211 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005212 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5213 config->sample_rate,
5214 config->format,
5215 channel_count,
5216 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005217 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005218 in->config.rate = config->sample_rate;
5219 in->af_period_multiplier = 1;
5220 }
5221 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5222 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005223 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005225 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005226 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005227
Kevin Rocarda325aa22018-04-03 09:15:52 -07005228
5229 register_format(in->format, in->supported_formats);
5230 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5231 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5232
Andy Hungd13f0d32017-06-12 13:58:37 -07005233 in->error_log = error_log_create(
5234 ERROR_LOG_ENTRIES,
5235 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5236
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005237 /* This stream could be for sound trigger lab,
5238 get sound trigger pcm if present */
5239 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005241 lock_input_stream(in);
5242 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5243 pthread_mutex_lock(&adev->lock);
5244 in->card_status = adev->card_status;
5245 pthread_mutex_unlock(&adev->lock);
5246 pthread_mutex_unlock(&in->lock);
5247
vivek mehta4a824772017-06-08 19:05:49 -07005248 stream_app_type_cfg_init(&in->app_type_cfg);
5249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005250 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005251 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005252 return 0;
5253
5254err_open:
5255 free(in);
5256 *stream_in = NULL;
5257 return ret;
5258}
5259
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005260static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261 struct audio_stream_in *stream)
5262{
Andy Hungd13f0d32017-06-12 13:58:37 -07005263 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005264 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005265
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005266 // must deregister from sndmonitor first to prevent races
5267 // between the callback and close_stream
5268 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005269 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005270
5271 error_log_destroy(in->error_log);
5272 in->error_log = NULL;
5273
Andy Hung0dbb52b2017-08-09 13:51:38 -07005274 pthread_mutex_destroy(&in->pre_lock);
5275 pthread_mutex_destroy(&in->lock);
5276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005277 free(stream);
5278
5279 return;
5280}
5281
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005282static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005283{
5284 return 0;
5285}
5286
Andy Hung31aca912014-03-20 17:14:59 -07005287/* verifies input and output devices and their capabilities.
5288 *
5289 * This verification is required when enabling extended bit-depth or
5290 * sampling rates, as not all qcom products support it.
5291 *
5292 * Suitable for calling only on initialization such as adev_open().
5293 * It fills the audio_device use_case_table[] array.
5294 *
5295 * Has a side-effect that it needs to configure audio routing / devices
5296 * in order to power up the devices and read the device parameters.
5297 * It does not acquire any hw device lock. Should restore the devices
5298 * back to "normal state" upon completion.
5299 */
5300static int adev_verify_devices(struct audio_device *adev)
5301{
5302 /* enumeration is a bit difficult because one really wants to pull
5303 * the use_case, device id, etc from the hidden pcm_device_table[].
5304 * In this case there are the following use cases and device ids.
5305 *
5306 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5307 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005308 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005309 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5310 * [USECASE_AUDIO_RECORD] = {0, 0},
5311 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5312 * [USECASE_VOICE_CALL] = {2, 2},
5313 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005314 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005315 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5316 */
5317
5318 /* should be the usecases enabled in adev_open_input_stream() */
5319 static const int test_in_usecases[] = {
5320 USECASE_AUDIO_RECORD,
5321 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5322 };
5323 /* should be the usecases enabled in adev_open_output_stream()*/
5324 static const int test_out_usecases[] = {
5325 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5326 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5327 };
5328 static const usecase_type_t usecase_type_by_dir[] = {
5329 PCM_PLAYBACK,
5330 PCM_CAPTURE,
5331 };
5332 static const unsigned flags_by_dir[] = {
5333 PCM_OUT,
5334 PCM_IN,
5335 };
5336
5337 size_t i;
5338 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005339 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005340 char info[512]; /* for possible debug info */
5341
5342 for (dir = 0; dir < 2; ++dir) {
5343 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5344 const unsigned flags_dir = flags_by_dir[dir];
5345 const size_t testsize =
5346 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5347 const int *testcases =
5348 dir ? test_in_usecases : test_out_usecases;
5349 const audio_devices_t audio_device =
5350 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5351
5352 for (i = 0; i < testsize; ++i) {
5353 const audio_usecase_t audio_usecase = testcases[i];
5354 int device_id;
5355 snd_device_t snd_device;
5356 struct pcm_params **pparams;
5357 struct stream_out out;
5358 struct stream_in in;
5359 struct audio_usecase uc_info;
5360 int retval;
5361
5362 pparams = &adev->use_case_table[audio_usecase];
5363 pcm_params_free(*pparams); /* can accept null input */
5364 *pparams = NULL;
5365
5366 /* find the device ID for the use case (signed, for error) */
5367 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5368 if (device_id < 0)
5369 continue;
5370
5371 /* prepare structures for device probing */
5372 memset(&uc_info, 0, sizeof(uc_info));
5373 uc_info.id = audio_usecase;
5374 uc_info.type = usecase_type;
5375 if (dir) {
5376 adev->active_input = &in;
5377 memset(&in, 0, sizeof(in));
5378 in.device = audio_device;
5379 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5380 uc_info.stream.in = &in;
5381 } else {
5382 adev->active_input = NULL;
5383 }
5384 memset(&out, 0, sizeof(out));
5385 out.devices = audio_device; /* only field needed in select_devices */
5386 uc_info.stream.out = &out;
5387 uc_info.devices = audio_device;
5388 uc_info.in_snd_device = SND_DEVICE_NONE;
5389 uc_info.out_snd_device = SND_DEVICE_NONE;
5390 list_add_tail(&adev->usecase_list, &uc_info.list);
5391
5392 /* select device - similar to start_(in/out)put_stream() */
5393 retval = select_devices(adev, audio_usecase);
5394 if (retval >= 0) {
5395 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5396#if LOG_NDEBUG == 0
5397 if (*pparams) {
5398 ALOGV("%s: (%s) card %d device %d", __func__,
5399 dir ? "input" : "output", card_id, device_id);
5400 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005401 } else {
5402 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5403 }
5404#endif
5405 }
5406
5407 /* deselect device - similar to stop_(in/out)put_stream() */
5408 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005409 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005410 /* 2. Disable the rx device */
5411 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005412 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005413 list_remove(&uc_info.list);
5414 }
5415 }
5416 adev->active_input = NULL; /* restore adev state */
5417 return 0;
5418}
5419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005420static int adev_close(hw_device_t *device)
5421{
Andy Hung31aca912014-03-20 17:14:59 -07005422 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005423 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005424
5425 if (!adev)
5426 return 0;
5427
5428 pthread_mutex_lock(&adev_init_lock);
5429
5430 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005431 audio_extn_snd_mon_unregister_listener(adev);
5432 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005433 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005434 audio_route_free(adev->audio_route);
5435 free(adev->snd_dev_ref_cnt);
5436 platform_deinit(adev->platform);
5437 audio_extn_extspk_deinit(adev->extspk);
5438 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005439 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005440 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5441 pcm_params_free(adev->use_case_table[i]);
5442 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005443 if (adev->adm_deinit)
5444 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005445 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005446 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005447 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005448
5449 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451 return 0;
5452}
5453
Glenn Kasten4f993392014-05-14 07:30:48 -07005454/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5455 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5456 * just that it _might_ work.
5457 */
5458static int period_size_is_plausible_for_low_latency(int period_size)
5459{
5460 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005461 case 48:
5462 case 96:
5463 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005464 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005465 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005466 case 240:
5467 case 320:
5468 case 480:
5469 return 1;
5470 default:
5471 return 0;
5472 }
5473}
5474
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005475static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5476{
5477 int card;
5478 card_status_t status;
5479
5480 if (!parms)
5481 return;
5482
5483 if (parse_snd_card_status(parms, &card, &status) < 0)
5484 return;
5485
5486 pthread_mutex_lock(&adev->lock);
5487 bool valid_cb = (card == adev->snd_card);
5488 if (valid_cb) {
5489 if (adev->card_status != status) {
5490 adev->card_status = status;
5491 platform_snd_card_update(adev->platform, status);
5492 }
5493 }
5494 pthread_mutex_unlock(&adev->lock);
5495 return;
5496}
5497
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005498/* out and adev lock held */
5499static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5500{
5501 struct audio_usecase *uc_info;
5502 float left_p;
5503 float right_p;
5504 audio_devices_t devices;
5505
5506 uc_info = get_usecase_from_list(adev, out->usecase);
5507 if (uc_info == NULL) {
5508 ALOGE("%s: Could not find the usecase (%d) in the list",
5509 __func__, out->usecase);
5510 return -EINVAL;
5511 }
5512
5513 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5514 out->usecase, use_case_table[out->usecase]);
5515
5516 if (restore) {
5517 // restore A2DP device for active usecases and unmute if required
5518 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5519 !is_a2dp_device(uc_info->out_snd_device)) {
5520 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5521 select_devices(adev, uc_info->id);
5522 pthread_mutex_lock(&out->compr_mute_lock);
5523 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5524 (out->a2dp_compress_mute)) {
5525 out->a2dp_compress_mute = false;
5526 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5527 }
5528 pthread_mutex_unlock(&out->compr_mute_lock);
5529 }
5530 } else {
5531 // mute compress stream if suspended
5532 pthread_mutex_lock(&out->compr_mute_lock);
5533 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5534 (!out->a2dp_compress_mute)) {
5535 if (!out->standby) {
5536 ALOGD("%s: selecting speaker and muting stream", __func__);
5537 devices = out->devices;
5538 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5539 left_p = out->volume_l;
5540 right_p = out->volume_r;
5541 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5542 compress_pause(out->compr);
5543 set_compr_volume(&out->stream, 0.0f, 0.0f);
5544 out->a2dp_compress_mute = true;
5545 select_devices(adev, out->usecase);
5546 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5547 compress_resume(out->compr);
5548 out->devices = devices;
5549 out->volume_l = left_p;
5550 out->volume_r = right_p;
5551 }
5552 }
5553 pthread_mutex_unlock(&out->compr_mute_lock);
5554 }
5555 ALOGV("%s: exit", __func__);
5556 return 0;
5557}
5558
5559int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5560{
5561 int ret = 0;
5562
5563 lock_output_stream(out);
5564 pthread_mutex_lock(&adev->lock);
5565
5566 ret = check_a2dp_restore_l(adev, out, restore);
5567
5568 pthread_mutex_unlock(&adev->lock);
5569 pthread_mutex_unlock(&out->lock);
5570 return ret;
5571}
5572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573static int adev_open(const hw_module_t *module, const char *name,
5574 hw_device_t **device)
5575{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005576 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005577
Eric Laurent2bafff12016-03-17 12:17:23 -07005578 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005579 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005580 pthread_mutex_lock(&adev_init_lock);
5581 if (audio_device_ref_count != 0) {
5582 *device = &adev->device.common;
5583 audio_device_ref_count++;
5584 ALOGV("%s: returning existing instance of adev", __func__);
5585 ALOGV("%s: exit", __func__);
5586 pthread_mutex_unlock(&adev_init_lock);
5587 return 0;
5588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005589 adev = calloc(1, sizeof(struct audio_device));
5590
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005591 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005593 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5594 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5595 adev->device.common.module = (struct hw_module_t *)module;
5596 adev->device.common.close = adev_close;
5597
5598 adev->device.init_check = adev_init_check;
5599 adev->device.set_voice_volume = adev_set_voice_volume;
5600 adev->device.set_master_volume = adev_set_master_volume;
5601 adev->device.get_master_volume = adev_get_master_volume;
5602 adev->device.set_master_mute = adev_set_master_mute;
5603 adev->device.get_master_mute = adev_get_master_mute;
5604 adev->device.set_mode = adev_set_mode;
5605 adev->device.set_mic_mute = adev_set_mic_mute;
5606 adev->device.get_mic_mute = adev_get_mic_mute;
5607 adev->device.set_parameters = adev_set_parameters;
5608 adev->device.get_parameters = adev_get_parameters;
5609 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5610 adev->device.open_output_stream = adev_open_output_stream;
5611 adev->device.close_output_stream = adev_close_output_stream;
5612 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005614 adev->device.close_input_stream = adev_close_input_stream;
5615 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005616 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005617
5618 /* Set the default route before the PCM stream is opened */
5619 pthread_mutex_lock(&adev->lock);
5620 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005621 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005622 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005623 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005624 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005625 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005626 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005627 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005628 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005629 pthread_mutex_unlock(&adev->lock);
5630
5631 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005632 adev->platform = platform_init(adev);
5633 if (!adev->platform) {
5634 free(adev->snd_dev_ref_cnt);
5635 free(adev);
5636 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5637 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005638 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005639 return -EINVAL;
5640 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005641 adev->extspk = audio_extn_extspk_init(adev);
5642
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005643 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5644 if (adev->visualizer_lib == NULL) {
5645 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5646 } else {
5647 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5648 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005649 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005650 "visualizer_hal_start_output");
5651 adev->visualizer_stop_output =
5652 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5653 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005654 }
5655
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005656 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5657 if (adev->offload_effects_lib == NULL) {
5658 ALOGW("%s: DLOPEN failed for %s", __func__,
5659 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5660 } else {
5661 ALOGV("%s: DLOPEN successful for %s", __func__,
5662 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5663 adev->offload_effects_start_output =
5664 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5665 "offload_effects_bundle_hal_start_output");
5666 adev->offload_effects_stop_output =
5667 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5668 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005669 }
5670
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005671 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5672 if (adev->adm_lib == NULL) {
5673 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5674 } else {
5675 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5676 adev->adm_init = (adm_init_t)
5677 dlsym(adev->adm_lib, "adm_init");
5678 adev->adm_deinit = (adm_deinit_t)
5679 dlsym(adev->adm_lib, "adm_deinit");
5680 adev->adm_register_input_stream = (adm_register_input_stream_t)
5681 dlsym(adev->adm_lib, "adm_register_input_stream");
5682 adev->adm_register_output_stream = (adm_register_output_stream_t)
5683 dlsym(adev->adm_lib, "adm_register_output_stream");
5684 adev->adm_deregister_stream = (adm_deregister_stream_t)
5685 dlsym(adev->adm_lib, "adm_deregister_stream");
5686 adev->adm_request_focus = (adm_request_focus_t)
5687 dlsym(adev->adm_lib, "adm_request_focus");
5688 adev->adm_abandon_focus = (adm_abandon_focus_t)
5689 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005690 adev->adm_set_config = (adm_set_config_t)
5691 dlsym(adev->adm_lib, "adm_set_config");
5692 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5693 dlsym(adev->adm_lib, "adm_request_focus_v2");
5694 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5695 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5696 adev->adm_on_routing_change = (adm_on_routing_change_t)
5697 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005698 }
5699
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005700 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005701 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005703 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005704
Andy Hung31aca912014-03-20 17:14:59 -07005705 if (k_enable_extended_precision)
5706 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707
Glenn Kasten4f993392014-05-14 07:30:48 -07005708 char value[PROPERTY_VALUE_MAX];
5709 int trial;
5710 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5711 trial = atoi(value);
5712 if (period_size_is_plausible_for_low_latency(trial)) {
5713 pcm_config_low_latency.period_size = trial;
5714 pcm_config_low_latency.start_threshold = trial / 4;
5715 pcm_config_low_latency.avail_min = trial / 4;
5716 configured_low_latency_capture_period_size = trial;
5717 }
5718 }
5719 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5720 trial = atoi(value);
5721 if (period_size_is_plausible_for_low_latency(trial)) {
5722 configured_low_latency_capture_period_size = trial;
5723 }
5724 }
5725
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005726 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5727
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005728 // commented as full set of app type cfg is sent from platform
5729 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005730 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005731
5732 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5733 af_period_multiplier = atoi(value);
5734 if (af_period_multiplier < 0) {
5735 af_period_multiplier = 2;
5736 } else if (af_period_multiplier > 4) {
5737 af_period_multiplier = 4;
5738 }
5739 ALOGV("new period_multiplier = %d", af_period_multiplier);
5740 }
5741
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005742 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005743 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005744
vivek mehta1a9b7c02015-06-25 11:49:38 -07005745 pthread_mutex_unlock(&adev_init_lock);
5746
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005747 if (adev->adm_init)
5748 adev->adm_data = adev->adm_init();
5749
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005750 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005751 audio_extn_snd_mon_init();
5752 pthread_mutex_lock(&adev->lock);
5753 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5754 adev->card_status = CARD_STATUS_ONLINE;
5755 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005756 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005757
Eric Laurent2bafff12016-03-17 12:17:23 -07005758 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759 return 0;
5760}
5761
5762static struct hw_module_methods_t hal_module_methods = {
5763 .open = adev_open,
5764};
5765
5766struct audio_module HAL_MODULE_INFO_SYM = {
5767 .common = {
5768 .tag = HARDWARE_MODULE_TAG,
5769 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5770 .hal_api_version = HARDWARE_HAL_API_VERSION,
5771 .id = AUDIO_HARDWARE_MODULE_ID,
5772 .name = "QCOM Audio HAL",
5773 .author = "Code Aurora Forum",
5774 .methods = &hal_module_methods,
5775 },
5776};