blob: e5a52d0b1133204602b1b2418dad3e3f16bcc509 [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{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800605
606 if (usecase == NULL)
607 return -EINVAL;
608
609 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
610
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800611 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800613 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 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);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800617 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000619 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700620 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700621 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int disable_audio_route(struct audio_device *adev,
628 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800632
633 if (usecase == NULL)
634 return -EINVAL;
635
636 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 if (usecase->type == PCM_CAPTURE)
638 snd_device = usecase->in_snd_device;
639 else
640 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500642 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700643 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700644 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000645 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647 ALOGV("%s: exit", __func__);
648 return 0;
649}
650
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800651int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700652 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700654 int i, num_devices = 0;
655 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800656 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800657 if (snd_device < SND_DEVICE_MIN ||
658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800660 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700663 platform_send_audio_calibration(adev->platform, snd_device);
664
vivek mehtade4849c2016-03-03 17:23:38 -0800665 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700666 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700667 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669 }
670
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700671 /* due to the possibility of calibration overwrite between listen
672 and audio, notify sound trigger hal before audio calibration is sent */
673 audio_extn_sound_trigger_update_device_status(snd_device,
674 ST_EVENT_SND_DEVICE_BUSY);
675
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 if (audio_extn_spkr_prot_is_enabled())
677 audio_extn_spkr_prot_calib_cancel(adev);
678
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, true);
680
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800682 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800683 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700686 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800687 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700688 }
689 if (audio_extn_spkr_prot_start_processing(snd_device)) {
690 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800691 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700693 } else if (platform_can_split_snd_device(snd_device,
694 &num_devices,
695 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700696 for (i = 0; i < num_devices; i++) {
697 enable_snd_device(adev, new_snd_devices[i]);
698 }
vivek mehtab6506412015-08-07 16:55:17 -0700699 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
702 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
703 ALOGE(" %s: Invalid sound device returned", __func__);
704 goto on_error;
705 }
Ed Tam70b5c142016-03-21 19:14:29 -0700706
Eric Laurent2e140aa2016-06-30 17:14:46 -0700707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700708
709 if (is_a2dp_device(snd_device) &&
710 (audio_extn_a2dp_start_playback() < 0)) {
711 ALOGE("%s: failed to configure A2DP control path", __func__);
712 goto on_error;
713 }
714
vivek mehtade4849c2016-03-03 17:23:38 -0800715 audio_route_apply_and_update_path(adev->audio_route, device_name);
716 }
717on_success:
718 adev->snd_dev_ref_cnt[snd_device]++;
719 ret_val = 0;
720on_error:
721 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722}
723
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800724int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[2];
729
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800730 if (snd_device < SND_DEVICE_MIN ||
731 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800732 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 return -EINVAL;
734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700735 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
736 ALOGE("%s: device ref cnt is already 0", __func__);
737 return -EINVAL;
738 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800739 audio_extn_tfa_98xx_disable_speaker(snd_device);
740
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 adev->snd_dev_ref_cnt[snd_device]--;
742 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800743 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800744
745 if (is_a2dp_device(snd_device))
746 audio_extn_a2dp_stop_playback();
747
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700748 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800749 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700750 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700751 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
752 audio_extn_spkr_prot_is_enabled()) {
753 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700754
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700755 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
756 // and does not use speaker swap. As this code causes a problem with device enable ref
757 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700758 // when speaker device is disabled, reset swap.
759 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700760 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700761
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700762 } else if (platform_can_split_snd_device(snd_device,
763 &num_devices,
764 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700765 for (i = 0; i < num_devices; i++) {
766 disable_snd_device(adev, new_snd_devices[i]);
767 }
vivek mehtab6506412015-08-07 16:55:17 -0700768 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700769 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800770 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
771 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
772 ALOGE(" %s: Invalid sound device returned", __func__);
773 return -EINVAL;
774 }
775
Eric Laurent2e140aa2016-06-30 17:14:46 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800777 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700778 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700779 audio_extn_sound_trigger_update_device_status(snd_device,
780 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 return 0;
784}
785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786/*
787 legend:
788 uc - existing usecase
789 new_uc - new usecase
790 d1, d11, d2 - SND_DEVICE enums
791 a1, a2 - corresponding ANDROID device enums
792 B, B1, B2 - backend strings
793
794case 1
795 uc->dev d1 (a1) B1
796 new_uc->dev d1 (a1), d2 (a2) B1, B2
797
798 resolution: disable and enable uc->dev on d1
799
800case 2
801 uc->dev d1 (a1) B1
802 new_uc->dev d11 (a1) B1
803
804 resolution: need to switch uc since d1 and d11 are related
805 (e.g. speaker and voice-speaker)
806 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
807
808case 3
809 uc->dev d1 (a1) B1
810 new_uc->dev d2 (a2) B2
811
812 resolution: no need to switch uc
813
814case 4
815 uc->dev d1 (a1) B
816 new_uc->dev d2 (a2) B
817
818 resolution: disable enable uc-dev on d2 since backends match
819 we cannot enable two streams on two different devices if they
820 share the same backend. e.g. if offload is on speaker device using
821 QUAD_MI2S backend and a low-latency stream is started on voice-handset
822 using the same backend, offload must also be switched to voice-handset.
823
824case 5
825 uc->dev d1 (a1) B
826 new_uc->dev d1 (a1), d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend.
831
832case 6
833 uc->dev d1 a1 B1
834 new_uc->dev d2 a1 B2
835
836 resolution: no need to switch
837
838case 7
839
840 uc->dev d1 (a1), d2 (a2) B1, B2
841 new_uc->dev d1 B1
842
843 resolution: no need to switch
844
845*/
846static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
847 struct audio_usecase *new_uc,
848 snd_device_t new_snd_device)
849{
850 audio_devices_t a1 = uc->stream.out->devices;
851 audio_devices_t a2 = new_uc->stream.out->devices;
852
853 snd_device_t d1 = uc->out_snd_device;
854 snd_device_t d2 = new_snd_device;
855
856 // Treat as a special case when a1 and a2 are not disjoint
857 if ((a1 != a2) && (a1 & a2)) {
858 snd_device_t d3[2];
859 int num_devices = 0;
860 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
861 &num_devices,
862 d3);
863 if (ret < 0) {
864 if (ret != -ENOSYS) {
865 ALOGW("%s failed to split snd_device %d",
866 __func__,
867 popcount(a1) > 1 ? d1 : d2);
868 }
869 goto end;
870 }
871
872 // NB: case 7 is hypothetical and isn't a practical usecase yet.
873 // But if it does happen, we need to give priority to d2 if
874 // the combo devices active on the existing usecase share a backend.
875 // This is because we cannot have a usecase active on a combo device
876 // and a new usecase requests one device in this combo pair.
877 if (platform_check_backends_match(d3[0], d3[1])) {
878 return d2; // case 5
879 } else {
880 return d1; // case 1
881 }
882 } else {
883 if (platform_check_backends_match(d1, d2)) {
884 return d2; // case 2, 4
885 } else {
886 return d1; // case 6, 3
887 }
888 }
889
890end:
891 return d2; // return whatever was calculated before.
892}
893
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700894static void check_and_route_playback_usecases(struct audio_device *adev,
895 struct audio_usecase *uc_info,
896 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897{
898 struct listnode *node;
899 struct audio_usecase *usecase;
900 bool switch_device[AUDIO_USECASE_MAX];
901 int i, num_uc_to_switch = 0;
902
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700903 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
904 uc_info,
905 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700906
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
912 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800913 audio_extn_a2dp_is_force_device_switch()) {
914 force_routing = true;
915 }
916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 /*
918 * This function is to make sure that all the usecases that are active on
919 * the hardware codec backend are always routed to any one device that is
920 * handled by the hardware codec.
921 * For example, if low-latency and deep-buffer usecases are currently active
922 * on speaker and out_set_parameters(headset) is received on low-latency
923 * output, then we have to make sure deep-buffer is also switched to headset,
924 * because of the limitation that both the devices cannot be enabled
925 * at the same time as they share the same backend.
926 */
927 /* Disable all the usecases on the shared backend other than the
928 specified usecase */
929 for (i = 0; i < AUDIO_USECASE_MAX; i++)
930 switch_device[i] = false;
931
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700934 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
935 continue;
936
937 if (force_routing ||
938 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700939 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
940 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700941 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700944 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900956 }
957 }
958
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700959 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700963 d_device = derive_playback_snd_device(usecase, uc_info,
964 snd_device);
965 enable_snd_device(adev, d_device);
966 /* Update the out_snd_device before enabling the audio route */
967 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 }
969 }
970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Re-route all the usecases on the shared backend other than the
972 specified usecase to new snd devices */
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700976 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 }
978 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980}
981
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700982static void check_and_route_capture_usecases(struct audio_device *adev,
983 struct audio_usecase *uc_info,
984 snd_device_t snd_device)
985{
986 struct listnode *node;
987 struct audio_usecase *usecase;
988 bool switch_device[AUDIO_USECASE_MAX];
989 int i, num_uc_to_switch = 0;
990
vivek mehta4ed66e62016-04-15 23:33:34 -0700991 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
992
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 /*
994 * This function is to make sure that all the active capture usecases
995 * are always routed to the same input sound device.
996 * For example, if audio-record and voice-call usecases are currently
997 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
998 * is received for voice call then we have to make sure that audio-record
999 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1000 * because of the limitation that two devices cannot be enabled
1001 * at the same time if they share the same backend.
1002 */
1003 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1004 switch_device[i] = false;
1005
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
1008 if (usecase->type != PCM_PLAYBACK &&
1009 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001010 usecase->in_snd_device != snd_device &&
1011 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001012 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1013 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001014 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001015 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001016 switch_device[usecase->id] = true;
1017 num_uc_to_switch++;
1018 }
1019 }
1020
1021 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 list_for_each(node, &adev->usecase_list) {
1023 usecase = node_to_item(node, struct audio_usecase, list);
1024 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001026 }
1027 }
1028
1029 list_for_each(node, &adev->usecase_list) {
1030 usecase = node_to_item(node, struct audio_usecase, list);
1031 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001032 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001033 }
1034 }
1035
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 /* Re-route all the usecases on the shared backend other than the
1037 specified usecase to new snd devices */
1038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
1040 /* Update the in_snd_device only before enabling the audio route */
1041 if (switch_device[usecase->id] ) {
1042 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001043 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001044 }
1045 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 }
1047}
1048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001050static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001052 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001053 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054
1055 switch (channels) {
1056 /*
1057 * Do not handle stereo output in Multi-channel cases
1058 * Stereo case is handled in normal playback path
1059 */
1060 case 6:
1061 ALOGV("%s: HDMI supports 5.1", __func__);
1062 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1063 break;
1064 case 8:
1065 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1066 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1067 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1068 break;
1069 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001070 ALOGE("HDMI does not support multi channel playback");
1071 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 break;
1073 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075}
1076
Andy Hung18859412017-08-09 11:47:21 -07001077static ssize_t read_usb_sup_sample_rates(bool is_playback,
1078 uint32_t *supported_sample_rates,
1079 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001080{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001081 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1082 supported_sample_rates,
1083 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001084#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001085 for (ssize_t i=0; i<count; i++) {
1086 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1087 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001088 }
1089#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001090 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001091}
1092
Haynes Mathew George569b7482017-05-08 14:44:27 -07001093static int read_usb_sup_channel_masks(bool is_playback,
1094 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001095 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001096{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001097 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001098 int channel_count;
1099 uint32_t num_masks = 0;
1100 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1101 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001102 }
Eric Laurent74b55762017-07-09 17:04:53 -07001103 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001104 // start from 2 channels as framework currently doesn't support mono.
1105 // TODO: consider only supporting channel index masks beyond stereo here.
1106 for (channel_count = FCC_2;
1107 channel_count <= channels && num_masks < max_masks;
1108 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001109 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1110 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001111 for (channel_count = FCC_2;
1112 channel_count <= channels && num_masks < max_masks;
1113 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001114 supported_channel_masks[num_masks++] =
1115 audio_channel_mask_for_index_assignment_from_count(channel_count);
1116 }
1117 } else {
1118 // For capture we report all supported channel masks from 1 channel up.
1119 channel_count = MIN_CHANNEL_COUNT;
1120 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1121 // indexed mask
1122 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1123 supported_channel_masks[num_masks++] =
1124 audio_channel_in_mask_from_count(channel_count);
1125 }
1126 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001127#ifdef NDEBUG
1128 for (size_t i = 0; i < num_masks; ++i) {
1129 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1130 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1131 }
1132#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001133 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001134}
1135
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001136static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001137 audio_format_t *supported_formats,
1138 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001139{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001140 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001141 switch (bitwidth) {
1142 case 24:
1143 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001144 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001145 break;
1146 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001148 break;
1149 case 16:
1150 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001152 break;
1153 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 ALOGV("%s: %s supported format %d", __func__,
1155 is_playback ? "P" : "C", bitwidth);
1156 return 1;
1157}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001158
Haynes Mathew George569b7482017-05-08 14:44:27 -07001159static int read_usb_sup_params_and_compare(bool is_playback,
1160 audio_format_t *format,
1161 audio_format_t *supported_formats,
1162 uint32_t max_formats,
1163 audio_channel_mask_t *mask,
1164 audio_channel_mask_t *supported_channel_masks,
1165 uint32_t max_masks,
1166 uint32_t *rate,
1167 uint32_t *supported_sample_rates,
1168 uint32_t max_rates) {
1169 int ret = 0;
1170 int num_formats;
1171 int num_masks;
1172 int num_rates;
1173 int i;
1174
1175 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1176 max_formats);
1177 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1178 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001179
Haynes Mathew George569b7482017-05-08 14:44:27 -07001180 num_rates = read_usb_sup_sample_rates(is_playback,
1181 supported_sample_rates, max_rates);
1182
1183#define LUT(table, len, what, dflt) \
1184 for (i=0; i<len && (table[i] != what); i++); \
1185 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1186
1187 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1188 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1189 LUT(supported_sample_rates, num_rates, *rate, 0);
1190
1191#undef LUT
1192 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001193}
1194
Andy Hungd9653bd2017-08-01 19:31:39 -07001195static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1196{
1197 // Check if usb is ready.
1198 // The usb device may have been removed quickly after insertion and hence
1199 // no longer available. This will show up as empty channel masks, or rates.
1200
1201 pthread_mutex_lock(&adev->lock);
1202 uint32_t supported_sample_rate;
1203
1204 // we consider usb ready if we can fetch at least one sample rate.
1205 const bool ready = read_usb_sup_sample_rates(
1206 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1207 pthread_mutex_unlock(&adev->lock);
1208 return ready;
1209}
1210
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001211static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1212{
1213 struct audio_usecase *usecase;
1214 struct listnode *node;
1215
1216 list_for_each(node, &adev->usecase_list) {
1217 usecase = node_to_item(node, struct audio_usecase, list);
1218 if (usecase->type == VOICE_CALL) {
1219 ALOGV("%s: usecase id %d", __func__, usecase->id);
1220 return usecase->id;
1221 }
1222 }
1223 return USECASE_INVALID;
1224}
1225
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001226struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1227 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228{
1229 struct audio_usecase *usecase;
1230 struct listnode *node;
1231
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (usecase->id == uc_id)
1235 return usecase;
1236 }
1237 return NULL;
1238}
1239
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001240static bool force_device_switch(struct audio_usecase *usecase)
1241{
1242 if (usecase->stream.out == NULL) {
1243 ALOGE("%s: stream.out is NULL", __func__);
1244 return false;
1245 }
1246
1247 // Force all A2DP output devices to reconfigure for proper AFE encode format
1248 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1249 // in suspended state, hence try to trigger a retry when we again get a routing request.
1250 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1251 audio_extn_a2dp_is_force_device_switch()) {
1252 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1253 return true;
1254 }
1255
1256 return false;
1257}
1258
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001259int select_devices(struct audio_device *adev,
1260 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001262 snd_device_t out_snd_device = SND_DEVICE_NONE;
1263 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001264 struct audio_usecase *usecase = NULL;
1265 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001266 struct audio_usecase *hfp_usecase = NULL;
1267 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001268 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001270 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1271 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 usecase = get_usecase_from_list(adev, uc_id);
1274 if (usecase == NULL) {
1275 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1276 return -EINVAL;
1277 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001279 if ((usecase->type == VOICE_CALL) ||
1280 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001281 out_snd_device = platform_get_output_snd_device(adev->platform,
1282 usecase->stream.out->devices);
1283 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase->devices = usecase->stream.out->devices;
1285 } else {
1286 /*
1287 * If the voice call is active, use the sound devices of voice call usecase
1288 * so that it would not result any device switch. All the usecases will
1289 * be switched to new device when select_devices() is called for voice call
1290 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001291 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001293 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001294 vc_usecase = get_usecase_from_list(adev,
1295 get_voice_usecase_id_from_list(adev));
1296 if ((vc_usecase != NULL) &&
1297 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1298 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 in_snd_device = vc_usecase->in_snd_device;
1300 out_snd_device = vc_usecase->out_snd_device;
1301 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001302 } else if (audio_extn_hfp_is_active(adev)) {
1303 hfp_ucid = audio_extn_hfp_get_usecase();
1304 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1305 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1306 in_snd_device = hfp_usecase->in_snd_device;
1307 out_snd_device = hfp_usecase->out_snd_device;
1308 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 }
1310 if (usecase->type == PCM_PLAYBACK) {
1311 usecase->devices = usecase->stream.out->devices;
1312 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001313 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001314 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001315
Eric Laurentb23d5282013-05-14 15:27:20 -07001316 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001318
1319 if (voip_usecase)
1320 voip_out = voip_usecase->stream.out;
1321
1322 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001324 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001325 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001326 select_devices(adev, adev->active_input->usecase);
1327 }
1328 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 } else if (usecase->type == PCM_CAPTURE) {
1330 usecase->devices = usecase->stream.in->device;
1331 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001332 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001333 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001334 if (adev->active_input &&
1335 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1336 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001337
1338 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1339 USECASE_AUDIO_PLAYBACK_VOIP);
1340
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001341 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001342 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1343 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001344 } else if (voip_usecase) {
1345 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001346 } else if (adev->primary_output) {
1347 out_device = adev->primary_output->devices;
1348 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001349 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001350 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001351 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 }
1353 }
1354
1355 if (out_snd_device == usecase->out_snd_device &&
1356 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001357 if (!force_device_switch(usecase))
1358 return 0;
1359 }
1360
1361 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1362 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1363 return 0;
1364 }
1365
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001366 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1367 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001368 (!audio_extn_a2dp_is_ready())) {
1369 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001370 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1371 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1372 else
1373 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 }
1375
Eric Laurent2bafff12016-03-17 12:17:23 -07001376 if (out_snd_device != SND_DEVICE_NONE &&
1377 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1378 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1379 __func__,
1380 use_case_table[uc_id],
1381 adev->last_logged_snd_device[uc_id][0],
1382 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1383 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1384 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1385 -1,
1386 out_snd_device,
1387 platform_get_snd_device_name(out_snd_device),
1388 platform_get_snd_device_acdb_id(out_snd_device));
1389 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1390 }
1391 if (in_snd_device != SND_DEVICE_NONE &&
1392 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1393 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1394 __func__,
1395 use_case_table[uc_id],
1396 adev->last_logged_snd_device[uc_id][1],
1397 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1398 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1399 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1400 -1,
1401 in_snd_device,
1402 platform_get_snd_device_name(in_snd_device),
1403 platform_get_snd_device_acdb_id(in_snd_device));
1404 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1405 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001406
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407 /*
1408 * Limitation: While in call, to do a device switch we need to disable
1409 * and enable both RX and TX devices though one of them is same as current
1410 * device.
1411 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001412 if ((usecase->type == VOICE_CALL) &&
1413 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1414 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001415 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001416 /* Disable sidetone only if voice call already exists */
1417 if (voice_is_call_state_active(adev))
1418 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001419 }
1420
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421 /* Disable current sound devices */
1422 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001423 disable_audio_route(adev, usecase);
1424 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 }
1426
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001428 disable_audio_route(adev, usecase);
1429 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430 }
1431
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001432 /* Applicable only on the targets that has external modem.
1433 * New device information should be sent to modem before enabling
1434 * the devices to reduce in-call device switch time.
1435 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001436 if ((usecase->type == VOICE_CALL) &&
1437 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1438 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001439 status = platform_switch_voice_call_enable_device_config(adev->platform,
1440 out_snd_device,
1441 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001442 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001443
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001444 /* Enable new sound devices */
1445 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001446 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001447 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1448 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001449 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001450 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451 }
1452
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001453 if (in_snd_device != SND_DEVICE_NONE) {
1454 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001455 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001456 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457
Eric Laurentb23d5282013-05-14 15:27:20 -07001458 if (usecase->type == VOICE_CALL)
1459 status = platform_switch_voice_call_device_post(adev->platform,
1460 out_snd_device,
1461 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001462
sangwoo170731f2013-06-08 15:36:36 +09001463 usecase->in_snd_device = in_snd_device;
1464 usecase->out_snd_device = out_snd_device;
1465
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001466 audio_extn_tfa_98xx_set_mode();
1467
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001468 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001469
Jasmine Cha70771b62018-05-15 15:02:43 +08001470 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001471
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001472 /* Applicable only on the targets that has external modem.
1473 * Enable device command should be sent to modem only after
1474 * enabling voice call mixer controls
1475 */
vivek mehta765eb642015-08-07 19:46:06 -07001476 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001477 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1478 out_snd_device,
1479 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001480 /* Enable sidetone only if voice call already exists */
1481 if (voice_is_call_state_active(adev))
1482 voice_set_sidetone(adev, out_snd_device, true);
1483 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001484
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001485 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001486 struct stream_out *voip_out = voip_usecase->stream.out;
1487 audio_extn_utils_send_app_type_gain(adev,
1488 voip_out->app_type_cfg.app_type,
1489 &voip_out->app_type_cfg.gain[0]);
1490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491 return status;
1492}
1493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494static int stop_input_stream(struct stream_in *in)
1495{
1496 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 struct audio_usecase *uc_info;
1498 struct audio_device *adev = in->dev;
1499
Eric Laurent994a6932013-07-17 11:51:42 -07001500 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001502
1503 if (adev->active_input) {
1504 if (adev->active_input->usecase == in->usecase) {
1505 adev->active_input = NULL;
1506 } else {
1507 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1508 __func__,
1509 use_case_table[adev->active_input->usecase],
1510 use_case_table[in->usecase]);
1511 }
1512 }
1513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514 uc_info = get_usecase_from_list(adev, in->usecase);
1515 if (uc_info == NULL) {
1516 ALOGE("%s: Could not find the usecase (%d) in the list",
1517 __func__, in->usecase);
1518 return -EINVAL;
1519 }
1520
vivek mehta781065c2017-04-04 12:55:01 -07001521 /* Close in-call recording streams */
1522 voice_check_and_stop_incall_rec_usecase(adev, in);
1523
Eric Laurent150dbfe2013-02-27 14:31:02 -08001524 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001525 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001526
1527 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001528 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001530 list_remove(&uc_info->list);
1531 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532
Eric Laurent994a6932013-07-17 11:51:42 -07001533 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 return ret;
1535}
1536
1537int start_input_stream(struct stream_in *in)
1538{
1539 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001540 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541 struct audio_usecase *uc_info;
1542 struct audio_device *adev = in->dev;
1543
Eric Laurent994a6932013-07-17 11:51:42 -07001544 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001545
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001546 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1547 return -EIO;
1548
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001549 if (in->card_status == CARD_STATUS_OFFLINE ||
1550 adev->card_status == CARD_STATUS_OFFLINE) {
1551 ALOGW("in->card_status or adev->card_status offline, try again");
1552 ret = -EAGAIN;
1553 goto error_config;
1554 }
1555
vivek mehta781065c2017-04-04 12:55:01 -07001556 /* Check if source matches incall recording usecase criteria */
1557 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1558 if (ret)
1559 goto error_config;
1560 else
1561 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1562
Eric Laurentb23d5282013-05-14 15:27:20 -07001563 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564 if (in->pcm_device_id < 0) {
1565 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1566 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001567 ret = -EINVAL;
1568 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570
1571 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001572 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1573 uc_info->id = in->usecase;
1574 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001575 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001576 uc_info->devices = in->device;
1577 uc_info->in_snd_device = SND_DEVICE_NONE;
1578 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001580 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001581
Wei Wangf4837d52017-11-21 14:51:20 -08001582 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001583 audio_extn_perf_lock_acquire();
1584
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001585 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001586
Eric Laurent0e46adf2016-12-16 12:49:24 -08001587 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001588 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001589 ALOGE("%s: pcm stream not ready", __func__);
1590 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001591 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001592 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001593 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001594 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1595 goto error_open;
1596 }
1597 } else {
1598 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1599 unsigned int pcm_open_retry_count = 0;
1600
1601 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1602 flags |= PCM_MMAP | PCM_NOIRQ;
1603 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1604 } else if (in->realtime) {
1605 flags |= PCM_MMAP | PCM_NOIRQ;
1606 }
1607
1608 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1609 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1610
1611 while (1) {
1612 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1613 flags, &in->config);
1614 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1615 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1616 if (in->pcm != NULL) {
1617 pcm_close(in->pcm);
1618 in->pcm = NULL;
1619 }
1620 if (pcm_open_retry_count-- == 0) {
1621 ret = -EIO;
1622 goto error_open;
1623 }
1624 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1625 continue;
1626 }
1627 break;
1628 }
1629
1630 ALOGV("%s: pcm_prepare", __func__);
1631 ret = pcm_prepare(in->pcm);
1632 if (ret < 0) {
1633 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001634 pcm_close(in->pcm);
1635 in->pcm = NULL;
1636 goto error_open;
1637 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001638 if (in->realtime) {
1639 ret = pcm_start(in->pcm);
1640 if (ret < 0) {
1641 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1642 pcm_close(in->pcm);
1643 in->pcm = NULL;
1644 goto error_open;
1645 }
1646 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001647 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001648 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001649 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001650 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001651 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001652
Eric Laurent0e46adf2016-12-16 12:49:24 -08001653 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001654
1655error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001657 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001658 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001659
1660error_config:
1661 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001662 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001663 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664}
1665
Eric Laurenta1478072015-09-21 17:21:52 -07001666void lock_input_stream(struct stream_in *in)
1667{
1668 pthread_mutex_lock(&in->pre_lock);
1669 pthread_mutex_lock(&in->lock);
1670 pthread_mutex_unlock(&in->pre_lock);
1671}
1672
1673void lock_output_stream(struct stream_out *out)
1674{
1675 pthread_mutex_lock(&out->pre_lock);
1676 pthread_mutex_lock(&out->lock);
1677 pthread_mutex_unlock(&out->pre_lock);
1678}
1679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680/* must be called with out->lock locked */
1681static int send_offload_cmd_l(struct stream_out* out, int command)
1682{
1683 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1684
1685 ALOGVV("%s %d", __func__, command);
1686
1687 cmd->cmd = command;
1688 list_add_tail(&out->offload_cmd_list, &cmd->node);
1689 pthread_cond_signal(&out->offload_cond);
1690 return 0;
1691}
1692
1693/* must be called iwth out->lock locked */
1694static void stop_compressed_output_l(struct stream_out *out)
1695{
1696 out->offload_state = OFFLOAD_STATE_IDLE;
1697 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001698 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001699 if (out->compr != NULL) {
1700 compress_stop(out->compr);
1701 while (out->offload_thread_blocked) {
1702 pthread_cond_wait(&out->cond, &out->lock);
1703 }
1704 }
1705}
1706
1707static void *offload_thread_loop(void *context)
1708{
1709 struct stream_out *out = (struct stream_out *) context;
1710 struct listnode *item;
1711
1712 out->offload_state = OFFLOAD_STATE_IDLE;
1713 out->playback_started = 0;
1714
1715 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1716 set_sched_policy(0, SP_FOREGROUND);
1717 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1718
1719 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001720 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001721 for (;;) {
1722 struct offload_cmd *cmd = NULL;
1723 stream_callback_event_t event;
1724 bool send_callback = false;
1725
1726 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1727 __func__, list_empty(&out->offload_cmd_list),
1728 out->offload_state);
1729 if (list_empty(&out->offload_cmd_list)) {
1730 ALOGV("%s SLEEPING", __func__);
1731 pthread_cond_wait(&out->offload_cond, &out->lock);
1732 ALOGV("%s RUNNING", __func__);
1733 continue;
1734 }
1735
1736 item = list_head(&out->offload_cmd_list);
1737 cmd = node_to_item(item, struct offload_cmd, node);
1738 list_remove(item);
1739
1740 ALOGVV("%s STATE %d CMD %d out->compr %p",
1741 __func__, out->offload_state, cmd->cmd, out->compr);
1742
1743 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1744 free(cmd);
1745 break;
1746 }
1747
1748 if (out->compr == NULL) {
1749 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001750 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001751 pthread_cond_signal(&out->cond);
1752 continue;
1753 }
1754 out->offload_thread_blocked = true;
1755 pthread_mutex_unlock(&out->lock);
1756 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001757 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1759 compress_wait(out->compr, -1);
1760 send_callback = true;
1761 event = STREAM_CBK_EVENT_WRITE_READY;
1762 break;
1763 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001764 compress_next_track(out->compr);
1765 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766 send_callback = true;
1767 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001768 /* Resend the metadata for next iteration */
1769 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 break;
1771 case OFFLOAD_CMD_DRAIN:
1772 compress_drain(out->compr);
1773 send_callback = true;
1774 event = STREAM_CBK_EVENT_DRAIN_READY;
1775 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001776 case OFFLOAD_CMD_ERROR:
1777 send_callback = true;
1778 event = STREAM_CBK_EVENT_ERROR;
1779 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001780 default:
1781 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1782 break;
1783 }
Eric Laurenta1478072015-09-21 17:21:52 -07001784 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 out->offload_thread_blocked = false;
1786 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001787 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001788 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001790 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001791 free(cmd);
1792 }
1793
1794 pthread_cond_signal(&out->cond);
1795 while (!list_empty(&out->offload_cmd_list)) {
1796 item = list_head(&out->offload_cmd_list);
1797 list_remove(item);
1798 free(node_to_item(item, struct offload_cmd, node));
1799 }
1800 pthread_mutex_unlock(&out->lock);
1801
1802 return NULL;
1803}
1804
1805static int create_offload_callback_thread(struct stream_out *out)
1806{
1807 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1808 list_init(&out->offload_cmd_list);
1809 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1810 offload_thread_loop, out);
1811 return 0;
1812}
1813
1814static int destroy_offload_callback_thread(struct stream_out *out)
1815{
Eric Laurenta1478072015-09-21 17:21:52 -07001816 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 stop_compressed_output_l(out);
1818 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1819
1820 pthread_mutex_unlock(&out->lock);
1821 pthread_join(out->offload_thread, (void **) NULL);
1822 pthread_cond_destroy(&out->offload_cond);
1823
1824 return 0;
1825}
1826
Eric Laurent07eeafd2013-10-06 12:52:49 -07001827static bool allow_hdmi_channel_config(struct audio_device *adev)
1828{
1829 struct listnode *node;
1830 struct audio_usecase *usecase;
1831 bool ret = true;
1832
1833 list_for_each(node, &adev->usecase_list) {
1834 usecase = node_to_item(node, struct audio_usecase, list);
1835 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1836 /*
1837 * If voice call is already existing, do not proceed further to avoid
1838 * disabling/enabling both RX and TX devices, CSD calls, etc.
1839 * Once the voice call done, the HDMI channels can be configured to
1840 * max channels of remaining use cases.
1841 */
1842 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001843 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001844 __func__);
1845 ret = false;
1846 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001847 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1848 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001849 "no change in HDMI channels", __func__);
1850 ret = false;
1851 break;
1852 }
1853 }
1854 }
1855 return ret;
1856}
1857
1858static int check_and_set_hdmi_channels(struct audio_device *adev,
1859 unsigned int channels)
1860{
1861 struct listnode *node;
1862 struct audio_usecase *usecase;
1863
1864 /* Check if change in HDMI channel config is allowed */
1865 if (!allow_hdmi_channel_config(adev))
1866 return 0;
1867
1868 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001869 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001870 return 0;
1871 }
1872
1873 platform_set_hdmi_channels(adev->platform, channels);
1874 adev->cur_hdmi_channels = channels;
1875
1876 /*
1877 * Deroute all the playback streams routed to HDMI so that
1878 * the back end is deactivated. Note that backend will not
1879 * be deactivated if any one stream is connected to it.
1880 */
1881 list_for_each(node, &adev->usecase_list) {
1882 usecase = node_to_item(node, struct audio_usecase, list);
1883 if (usecase->type == PCM_PLAYBACK &&
1884 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001885 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001886 }
1887 }
1888
1889 /*
1890 * Enable all the streams disabled above. Now the HDMI backend
1891 * will be activated with new channel configuration
1892 */
1893 list_for_each(node, &adev->usecase_list) {
1894 usecase = node_to_item(node, struct audio_usecase, list);
1895 if (usecase->type == PCM_PLAYBACK &&
1896 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001897 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001898 }
1899 }
1900
1901 return 0;
1902}
1903
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001904static int check_and_set_usb_service_interval(struct audio_device *adev,
1905 struct audio_usecase *uc_info,
1906 bool min)
1907{
1908 struct listnode *node;
1909 struct audio_usecase *usecase;
1910 bool switch_usecases = false;
1911 bool reconfig = false;
1912
1913 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1914 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1915 return -1;
1916
1917 /* set if the valid usecase do not already exist */
1918 list_for_each(node, &adev->usecase_list) {
1919 usecase = node_to_item(node, struct audio_usecase, list);
1920 if (usecase->type == PCM_PLAYBACK &&
1921 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1922 switch (usecase->id) {
1923 case USECASE_AUDIO_PLAYBACK_MMAP:
1924 case USECASE_AUDIO_PLAYBACK_ULL:
1925 // cannot reconfig while mmap/ull is present.
1926 return -1;
1927 default:
1928 switch_usecases = true;
1929 break;
1930 }
1931 }
1932 if (switch_usecases)
1933 break;
1934 }
1935 /*
1936 * client can try to set service interval in start_output_stream
1937 * to min or to 0 (i.e reset) in stop_output_stream .
1938 */
1939 unsigned long service_interval =
1940 audio_extn_usb_find_service_interval(min, true /*playback*/);
1941 int ret = platform_set_usb_service_interval(adev->platform,
1942 true /*playback*/,
1943 service_interval,
1944 &reconfig);
1945 /* no change or not supported or no active usecases */
1946 if (ret || !reconfig || !switch_usecases)
1947 return -1;
1948 return 0;
1949#undef VALID_USECASE
1950}
1951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001952static int stop_output_stream(struct stream_out *out)
1953{
1954 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 struct audio_usecase *uc_info;
1956 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001957 bool has_voip_usecase =
1958 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959
Eric Laurent994a6932013-07-17 11:51:42 -07001960 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001961 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 uc_info = get_usecase_from_list(adev, out->usecase);
1963 if (uc_info == NULL) {
1964 ALOGE("%s: Could not find the usecase (%d) in the list",
1965 __func__, out->usecase);
1966 return -EINVAL;
1967 }
1968
Haynes Mathew George41f86652014-06-17 14:22:15 -07001969 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1970 if (adev->visualizer_stop_output != NULL)
1971 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1972 if (adev->offload_effects_stop_output != NULL)
1973 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001974 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1975 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1976 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001977 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001978
Eric Laurent150dbfe2013-02-27 14:31:02 -08001979 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001980 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981
1982 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001983 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001985 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986
Eric Laurent0499d4f2014-08-25 22:39:29 -05001987 audio_extn_extspk_update(adev->extspk);
1988
Eric Laurent07eeafd2013-10-06 12:52:49 -07001989 /* Must be called after removing the usecase from list */
1990 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1991 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08001992 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001993 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1994 if (ret == 0) {
1995 /* default service interval was successfully updated,
1996 reopen USB backend with new service interval */
1997 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
1998 }
1999 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002000 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002001
HW Lee88512e92018-06-12 15:26:09 +08002002 if (has_voip_usecase ||
2003 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2004 struct listnode *node;
2005 struct audio_usecase *usecase;
2006 list_for_each(node, &adev->usecase_list) {
2007 usecase = node_to_item(node, struct audio_usecase, list);
2008 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2009 continue;
2010
2011 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2012 __func__, usecase->id, use_case_table[usecase->id],
2013 out->usecase, use_case_table[out->usecase]);
2014 select_devices(adev, usecase->id);
2015 }
2016 }
2017
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002018 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002019 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020 return ret;
2021}
2022
2023int start_output_stream(struct stream_out *out)
2024{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 struct audio_usecase *uc_info;
2027 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002028 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029
Eric Laurent994a6932013-07-17 11:51:42 -07002030 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002031 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002032
2033 if (out->card_status == CARD_STATUS_OFFLINE ||
2034 adev->card_status == CARD_STATUS_OFFLINE) {
2035 ALOGW("out->card_status or adev->card_status offline, try again");
2036 ret = -EAGAIN;
2037 goto error_config;
2038 }
2039
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002040 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2041 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002042 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002043 a2dp_combo = true;
2044 } else {
2045 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2046 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2047 ret = -EAGAIN;
2048 goto error_config;
2049 }
2050 }
2051 }
2052 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002053 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054 if (out->pcm_device_id < 0) {
2055 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2056 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002057 ret = -EINVAL;
2058 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 }
2060
2061 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2062 uc_info->id = out->usecase;
2063 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002064 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002065 uc_info->devices = out->devices;
2066 uc_info->in_snd_device = SND_DEVICE_NONE;
2067 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068
Eric Laurent07eeafd2013-10-06 12:52:49 -07002069 /* This must be called before adding this usecase to the list */
2070 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2071 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002072 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2073 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2074 /* USB backend is not reopened immediately.
2075 This is eventually done as part of select_devices */
2076 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002077
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002078 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002079
Wei Wangf4837d52017-11-21 14:51:20 -08002080 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002081 audio_extn_perf_lock_acquire();
2082
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002083 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2084 (!audio_extn_a2dp_is_ready())) {
2085 if (!a2dp_combo) {
2086 check_a2dp_restore_l(adev, out, false);
2087 } else {
2088 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002089 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2090 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2091 else
2092 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002093 select_devices(adev, out->usecase);
2094 out->devices = dev;
2095 }
2096 } else {
2097 select_devices(adev, out->usecase);
2098 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002099
Eric Laurent0499d4f2014-08-25 22:39:29 -05002100 audio_extn_extspk_update(adev->extspk);
2101
Andy Hung31aca912014-03-20 17:14:59 -07002102 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002103 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002104 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2105 out->pcm = NULL;
2106 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2107 COMPRESS_IN, &out->compr_config);
2108 if (out->compr && !is_compress_ready(out->compr)) {
2109 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2110 compress_close(out->compr);
2111 out->compr = NULL;
2112 ret = -EIO;
2113 goto error_open;
2114 }
2115 if (out->offload_callback)
2116 compress_nonblock(out->compr, out->non_blocking);
2117
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002118 if (adev->visualizer_start_output != NULL) {
2119 int capture_device_id =
2120 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2121 PCM_CAPTURE);
2122 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2123 adev->snd_card, capture_device_id);
2124 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002125 if (adev->offload_effects_start_output != NULL)
2126 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2127 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002128 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002129 ALOGE("%s: pcm stream not ready", __func__);
2130 goto error_open;
2131 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002132 ret = pcm_start(out->pcm);
2133 if (ret < 0) {
2134 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2135 goto error_open;
2136 }
2137 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002138 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002139 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002140
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002141 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2142 flags |= PCM_MMAP | PCM_NOIRQ;
2143 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002144 } else if (out->realtime) {
2145 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002146 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002147
2148 while (1) {
2149 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2150 flags, &out->config);
2151 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2152 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2153 if (out->pcm != NULL) {
2154 pcm_close(out->pcm);
2155 out->pcm = NULL;
2156 }
2157 if (pcm_open_retry_count-- == 0) {
2158 ret = -EIO;
2159 goto error_open;
2160 }
2161 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2162 continue;
2163 }
2164 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002165 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002166 ALOGV("%s: pcm_prepare", __func__);
2167 if (pcm_is_ready(out->pcm)) {
2168 ret = pcm_prepare(out->pcm);
2169 if (ret < 0) {
2170 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2171 pcm_close(out->pcm);
2172 out->pcm = NULL;
2173 goto error_open;
2174 }
2175 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002176 if (out->realtime) {
2177 ret = pcm_start(out->pcm);
2178 if (ret < 0) {
2179 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2180 pcm_close(out->pcm);
2181 out->pcm = NULL;
2182 goto error_open;
2183 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002184 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002185 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002186 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002187 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002188 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002189 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002190
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002191 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2192 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2193 audio_low_latency_hint_start();
2194 }
2195
vivek mehtae59cfb22017-06-16 15:57:11 -07002196 // consider a scenario where on pause lower layers are tear down.
2197 // so on resume, swap mixer control need to be sent only when
2198 // backend is active, hence rather than sending from enable device
2199 // sending it from start of streamtream
2200
2201 platform_set_swap_channels(adev, true);
2202
Eric Laurent994a6932013-07-17 11:51:42 -07002203 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002204 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002206 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002207 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002209error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002210 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211}
2212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213static int check_input_parameters(uint32_t sample_rate,
2214 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002215 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002217 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2218 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002219 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2220 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002221 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2222 return -EINVAL;
2223 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224
Eric Laurent74b55762017-07-09 17:04:53 -07002225 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2226 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002227 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002228 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002229 return -EINVAL;
2230 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231
2232 switch (sample_rate) {
2233 case 8000:
2234 case 11025:
2235 case 12000:
2236 case 16000:
2237 case 22050:
2238 case 24000:
2239 case 32000:
2240 case 44100:
2241 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002242 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243 break;
2244 default:
vivek mehtadae44712015-07-27 14:13:18 -07002245 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 return -EINVAL;
2247 }
2248
2249 return 0;
2250}
2251
Kevin Rocarda325aa22018-04-03 09:15:52 -07002252/** Add a value in a list if not already present.
2253 * @return true if value was successfully inserted or already present,
2254 * false if the list is full and does not contain the value.
2255 */
2256static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2257 for (size_t i = 0; i < list_length; i++) {
2258 if (list[i] == value) return true; // value is already present
2259 if (list[i] == 0) { // no values in this slot
2260 list[i] = value;
2261 return true; // value inserted
2262 }
2263 }
2264 return false; // could not insert value
2265}
2266
2267/** Add channel_mask in supported_channel_masks if not already present.
2268 * @return true if channel_mask was successfully inserted or already present,
2269 * false if supported_channel_masks is full and does not contain channel_mask.
2270 */
2271static void register_channel_mask(audio_channel_mask_t channel_mask,
2272 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2273 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2274 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2275}
2276
2277/** Add format in supported_formats if not already present.
2278 * @return true if format was successfully inserted or already present,
2279 * false if supported_formats is full and does not contain format.
2280 */
2281static void register_format(audio_format_t format,
2282 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2283 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2284 "%s: stream can not declare supporting its format %x", __func__, format);
2285}
2286/** Add sample_rate in supported_sample_rates if not already present.
2287 * @return true if sample_rate was successfully inserted or already present,
2288 * false if supported_sample_rates is full and does not contain sample_rate.
2289 */
2290static void register_sample_rate(uint32_t sample_rate,
2291 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2292 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2293 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2294}
2295
vivek mehtaa68fea62017-06-08 19:04:02 -07002296static size_t get_stream_buffer_size(size_t duration_ms,
2297 uint32_t sample_rate,
2298 audio_format_t format,
2299 int channel_count,
2300 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301{
2302 size_t size = 0;
2303
vivek mehtaa68fea62017-06-08 19:04:02 -07002304 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002305 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002306 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002307
2308 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309
Glenn Kasten4f993392014-05-14 07:30:48 -07002310 /* make sure the size is multiple of 32 bytes
2311 * At 48 kHz mono 16-bit PCM:
2312 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2313 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2314 */
2315 size += 0x1f;
2316 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002317
2318 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319}
2320
2321static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2322{
2323 struct stream_out *out = (struct stream_out *)stream;
2324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002325 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326}
2327
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002328static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329{
2330 return -ENOSYS;
2331}
2332
2333static size_t out_get_buffer_size(const struct audio_stream *stream)
2334{
2335 struct stream_out *out = (struct stream_out *)stream;
2336
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002337 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2338 return out->compr_config.fragment_size;
2339 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002340 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002341 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342}
2343
2344static uint32_t out_get_channels(const struct audio_stream *stream)
2345{
2346 struct stream_out *out = (struct stream_out *)stream;
2347
2348 return out->channel_mask;
2349}
2350
2351static audio_format_t out_get_format(const struct audio_stream *stream)
2352{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 struct stream_out *out = (struct stream_out *)stream;
2354
2355 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356}
2357
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002358static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359{
2360 return -ENOSYS;
2361}
2362
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002363/* must be called with out->lock locked */
2364static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365{
2366 struct stream_out *out = (struct stream_out *)stream;
2367 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002368 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002371 if (adev->adm_deregister_stream)
2372 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002373 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002375 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2376 if (out->pcm) {
2377 pcm_close(out->pcm);
2378 out->pcm = NULL;
2379 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002380 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002381 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002382 out->playback_started = false;
2383 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 } else {
2385 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002386 out->gapless_mdata.encoder_delay = 0;
2387 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 if (out->compr != NULL) {
2389 compress_close(out->compr);
2390 out->compr = NULL;
2391 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002392 }
Phil Burkbc991042017-02-24 08:06:44 -08002393 if (do_stop) {
2394 stop_output_stream(out);
2395 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002396 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002398 return 0;
2399}
2400
2401static int out_standby(struct audio_stream *stream)
2402{
2403 struct stream_out *out = (struct stream_out *)stream;
2404
2405 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2406 out->usecase, use_case_table[out->usecase]);
2407
2408 lock_output_stream(out);
2409 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002411 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 return 0;
2413}
2414
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002415static int out_on_error(struct audio_stream *stream)
2416{
2417 struct stream_out *out = (struct stream_out *)stream;
2418 struct audio_device *adev = out->dev;
2419 bool do_standby = false;
2420
2421 lock_output_stream(out);
2422 if (!out->standby) {
2423 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2424 stop_compressed_output_l(out);
2425 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2426 } else
2427 do_standby = true;
2428 }
2429 pthread_mutex_unlock(&out->lock);
2430
2431 if (do_standby)
2432 return out_standby(&out->stream.common);
2433
2434 return 0;
2435}
2436
Andy Hung7401c7c2016-09-21 12:41:21 -07002437static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438{
Andy Hung7401c7c2016-09-21 12:41:21 -07002439 struct stream_out *out = (struct stream_out *)stream;
2440
2441 // We try to get the lock for consistency,
2442 // but it isn't necessary for these variables.
2443 // If we're not in standby, we may be blocked on a write.
2444 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2445 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2446 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2447
2448 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002449 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002450 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002451
2452 // dump error info
2453 (void)error_log_dump(
2454 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002455
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456 return 0;
2457}
2458
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002459static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2460{
2461 int ret = 0;
2462 char value[32];
2463 struct compr_gapless_mdata tmp_mdata;
2464
2465 if (!out || !parms) {
2466 return -EINVAL;
2467 }
2468
2469 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2470 if (ret >= 0) {
2471 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2472 } else {
2473 return -EINVAL;
2474 }
2475
2476 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2477 if (ret >= 0) {
2478 tmp_mdata.encoder_padding = atoi(value);
2479 } else {
2480 return -EINVAL;
2481 }
2482
2483 out->gapless_mdata = tmp_mdata;
2484 out->send_new_metadata = 1;
2485 ALOGV("%s new encoder delay %u and padding %u", __func__,
2486 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2487
2488 return 0;
2489}
2490
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002491static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2492{
2493 return out == adev->primary_output || out == adev->voice_tx_output;
2494}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002495
Kevin Rocard1e02c882017-08-09 15:26:07 -07002496static int get_alive_usb_card(struct str_parms* parms) {
2497 int card;
2498 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2499 !audio_extn_usb_alive(card)) {
2500 return card;
2501 }
2502 return -ENODEV;
2503}
2504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2506{
2507 struct stream_out *out = (struct stream_out *)stream;
2508 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002509 struct audio_usecase *usecase;
2510 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 struct str_parms *parms;
2512 char value[32];
2513 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002514 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002515 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002516 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517
Eric Laurent2e140aa2016-06-30 17:14:46 -07002518 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002519 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520 parms = str_parms_create_str(kvpairs);
2521 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2522 if (ret >= 0) {
2523 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002524
Eric Laurenta1478072015-09-21 17:21:52 -07002525 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002526
2527 // The usb driver needs to be closed after usb device disconnection
2528 // otherwise audio is no longer played on the new usb devices.
2529 // By forcing the stream in standby, the usb stack refcount drops to 0
2530 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002531 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002532 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002533 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2534 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2535 out_standby_l(&out->stream.common);
2536 }
2537 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002538 }
2539
Eric Laurent150dbfe2013-02-27 14:31:02 -08002540 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002542 /*
2543 * When HDMI cable is unplugged the music playback is paused and
2544 * the policy manager sends routing=0. But the audioflinger
2545 * continues to write data until standby time (3sec).
2546 * As the HDMI core is turned off, the write gets blocked.
2547 * Avoid this by routing audio to speaker until standby.
2548 */
2549 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2550 val == AUDIO_DEVICE_NONE) {
2551 val = AUDIO_DEVICE_OUT_SPEAKER;
2552 }
2553
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002554 /*
2555 * When A2DP is disconnected the
2556 * music playback is paused and the policy manager sends routing=0
2557 * But the audioflingercontinues to write data until standby time
2558 * (3sec). As BT is turned off, the write gets blocked.
2559 * Avoid this by routing audio to speaker until standby.
2560 */
2561 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2562 (val == AUDIO_DEVICE_NONE) &&
2563 !audio_extn_a2dp_is_ready()) {
2564 val = AUDIO_DEVICE_OUT_SPEAKER;
2565 }
2566
2567 /* To avoid a2dp to sco overlapping / BT device improper state
2568 * check with BT lib about a2dp streaming support before routing
2569 */
2570 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2571 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002572 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002573 //combo usecase just by pass a2dp
2574 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2575 bypass_a2dp = true;
2576 } else {
2577 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2578 /* update device to a2dp and don't route as BT returned error
2579 * However it is still possible a2dp routing called because
2580 * of current active device disconnection (like wired headset)
2581 */
2582 out->devices = val;
2583 pthread_mutex_unlock(&out->lock);
2584 pthread_mutex_unlock(&adev->lock);
2585 status = -ENOSYS;
2586 goto routing_fail;
2587 }
2588 }
2589 }
2590
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002591 audio_devices_t new_dev = val;
2592
2593 // Workaround: If routing to an non existing usb device, fail gracefully
2594 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002595 int card;
2596 if (audio_is_usb_out_device(new_dev) &&
2597 (card = get_alive_usb_card(parms)) >= 0) {
2598
2599 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002600 pthread_mutex_unlock(&adev->lock);
2601 pthread_mutex_unlock(&out->lock);
2602 status = -ENOSYS;
2603 goto routing_fail;
2604 }
2605
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002606 /*
2607 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002608 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002609 * the select_devices(). But how do we undo this?
2610 *
2611 * For example, music playback is active on headset (deep-buffer usecase)
2612 * and if we go to ringtones and select a ringtone, low-latency usecase
2613 * will be started on headset+speaker. As we can't enable headset+speaker
2614 * and headset devices at the same time, select_devices() switches the music
2615 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2616 * So when the ringtone playback is completed, how do we undo the same?
2617 *
2618 * We are relying on the out_set_parameters() call on deep-buffer output,
2619 * once the ringtone playback is ended.
2620 * NOTE: We should not check if the current devices are same as new devices.
2621 * Because select_devices() must be called to switch back the music
2622 * playback to headset.
2623 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002624 if (new_dev != AUDIO_DEVICE_NONE) {
2625 bool same_dev = out->devices == new_dev;
2626 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002627
Eric Laurenta7657192014-10-09 21:09:33 -07002628 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002629 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002630 if (adev->mode == AUDIO_MODE_IN_CALL) {
2631 adev->current_call_output = out;
2632 ret = voice_start_call(adev);
2633 }
2634 } else {
2635 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002636 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002637 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002638 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002639
2640 if (!out->standby) {
2641 if (!same_dev) {
2642 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002643 // inform adm before actual routing to prevent glitches.
2644 if (adev->adm_on_routing_change) {
2645 adev->adm_on_routing_change(adev->adm_data,
2646 out->handle);
2647 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002648 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002649 if (!bypass_a2dp) {
2650 select_devices(adev, out->usecase);
2651 } else {
juyuchen9baad392018-06-05 19:02:10 +08002652 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2653 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2654 else
2655 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002656 select_devices(adev, out->usecase);
2657 out->devices = new_dev;
2658 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002659 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002660
2661 // on device switch force swap, lower functions will make sure
2662 // to check if swap is allowed or not.
2663
2664 if (!same_dev)
2665 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002666
2667 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2668 out->a2dp_compress_mute &&
2669 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2670 pthread_mutex_lock(&out->compr_mute_lock);
2671 out->a2dp_compress_mute = false;
2672 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2673 pthread_mutex_unlock(&out->compr_mute_lock);
2674 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002675 }
2676
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002677 }
2678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002680 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002681
2682 /*handles device and call state changes*/
2683 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002685 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002686
2687 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2688 parse_compress_metadata(out, parms);
2689 }
2690
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002692 ALOGV("%s: exit: code(%d)", __func__, status);
2693 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694}
2695
Haynes Mathew George569b7482017-05-08 14:44:27 -07002696static bool stream_get_parameter_channels(struct str_parms *query,
2697 struct str_parms *reply,
2698 audio_channel_mask_t *supported_channel_masks) {
2699 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002700 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002701 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002702 size_t i, j;
2703
2704 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2705 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 value[0] = '\0';
2707 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002708 while (supported_channel_masks[i] != 0) {
2709 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2710 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002711 if (!first) {
2712 strcat(value, "|");
2713 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002714 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 first = false;
2716 break;
2717 }
2718 }
2719 i++;
2720 }
2721 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002722 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002723 return ret >= 0;
2724}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002725
Haynes Mathew George569b7482017-05-08 14:44:27 -07002726static bool stream_get_parameter_formats(struct str_parms *query,
2727 struct str_parms *reply,
2728 audio_format_t *supported_formats) {
2729 int ret = -1;
2730 char value[256];
2731 int i;
2732
2733 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2734 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002735 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002736 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002737 case AUDIO_FORMAT_PCM_16_BIT:
2738 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2739 break;
2740 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2741 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2742 break;
2743 case AUDIO_FORMAT_PCM_32_BIT:
2744 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2745 break;
2746 default:
2747 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002748 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002749 break;
2750 }
2751 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002752 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002753 return ret >= 0;
2754}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002755
Haynes Mathew George569b7482017-05-08 14:44:27 -07002756static bool stream_get_parameter_rates(struct str_parms *query,
2757 struct str_parms *reply,
2758 uint32_t *supported_sample_rates) {
2759
2760 int i;
2761 char value[256];
2762 int ret = -1;
2763 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2764 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002765 value[0] = '\0';
2766 i=0;
2767 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002768 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002769 int avail = sizeof(value) - cursor;
2770 ret = snprintf(value + cursor, avail, "%s%d",
2771 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002772 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002773 if (ret < 0 || ret >= avail) {
2774 // if cursor is at the last element of the array
2775 // overwrite with \0 is duplicate work as
2776 // snprintf already put a \0 in place.
2777 // else
2778 // we had space to write the '|' at value[cursor]
2779 // (which will be overwritten) or no space to fill
2780 // the first element (=> cursor == 0)
2781 value[cursor] = '\0';
2782 break;
2783 }
2784 cursor += ret;
2785 ++i;
2786 }
2787 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2788 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002789 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002790 return ret >= 0;
2791}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002792
Haynes Mathew George569b7482017-05-08 14:44:27 -07002793static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2794{
2795 struct stream_out *out = (struct stream_out *)stream;
2796 struct str_parms *query = str_parms_create_str(keys);
2797 char *str;
2798 struct str_parms *reply = str_parms_create();
2799 bool replied = false;
2800 ALOGV("%s: enter: keys - %s", __func__, keys);
2801
2802 replied |= stream_get_parameter_channels(query, reply,
2803 &out->supported_channel_masks[0]);
2804 replied |= stream_get_parameter_formats(query, reply,
2805 &out->supported_formats[0]);
2806 replied |= stream_get_parameter_rates(query, reply,
2807 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002808 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002809 str = str_parms_to_str(reply);
2810 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002811 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 }
2813 str_parms_destroy(query);
2814 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002815 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 return str;
2817}
2818
2819static uint32_t out_get_latency(const struct audio_stream_out *stream)
2820{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002821 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002823 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2826 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002827 else if ((out->realtime) ||
2828 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002829 // since the buffer won't be filled up faster than realtime,
2830 // return a smaller number
2831 period_ms = (out->af_period_multiplier * out->config.period_size *
2832 1000) / (out->config.rate);
2833 hw_delay = platform_render_latency(out->usecase)/1000;
2834 return period_ms + hw_delay;
2835 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002836
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002837 latency = (out->config.period_count * out->config.period_size * 1000) /
2838 (out->config.rate);
2839
2840 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2841 latency += audio_extn_a2dp_get_encoder_latency();
2842
2843 return latency;
2844}
2845
2846static int set_compr_volume(struct audio_stream_out *stream, float left,
2847 float right)
2848{
2849 struct stream_out *out = (struct stream_out *)stream;
2850 int volume[2];
2851 char mixer_ctl_name[128];
2852 struct audio_device *adev = out->dev;
2853 struct mixer_ctl *ctl;
2854 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2855 PCM_PLAYBACK);
2856
2857 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2858 "Compress Playback %d Volume", pcm_device_id);
2859 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2860 if (!ctl) {
2861 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2862 __func__, mixer_ctl_name);
2863 return -EINVAL;
2864 }
2865 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2866 __func__, mixer_ctl_name, left, right);
2867 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2868 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2869 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2870
2871 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872}
2873
2874static int out_set_volume(struct audio_stream_out *stream, float left,
2875 float right)
2876{
Eric Laurenta9024de2013-04-04 09:19:12 -07002877 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002878 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002880 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002881 /* only take left channel into account: the API is for stereo anyway */
2882 out->muted = (left == 0.0f);
2883 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002885 pthread_mutex_lock(&out->compr_mute_lock);
2886 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2887 if (!out->a2dp_compress_mute)
2888 ret = set_compr_volume(stream, left, right);
2889 out->volume_l = left;
2890 out->volume_r = right;
2891 pthread_mutex_unlock(&out->compr_mute_lock);
2892 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002893 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002894 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2895 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2896 if (!out->standby) {
2897 // if in standby, cached volume will be sent after stream is opened
2898 audio_extn_utils_send_app_type_gain(out->dev,
2899 out->app_type_cfg.app_type,
2900 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002901 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002902 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002903 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002905 return -ENOSYS;
2906}
2907
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002908// note: this call is safe only if the stream_cb is
2909// removed first in close_output_stream (as is done now).
2910static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2911{
2912 if (!stream || !parms)
2913 return;
2914
2915 struct stream_out *out = (struct stream_out *)stream;
2916 struct audio_device *adev = out->dev;
2917
2918 card_status_t status;
2919 int card;
2920 if (parse_snd_card_status(parms, &card, &status) < 0)
2921 return;
2922
2923 pthread_mutex_lock(&adev->lock);
2924 bool valid_cb = (card == adev->snd_card);
2925 pthread_mutex_unlock(&adev->lock);
2926
2927 if (!valid_cb)
2928 return;
2929
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002930 lock_output_stream(out);
2931 if (out->card_status != status)
2932 out->card_status = status;
2933 pthread_mutex_unlock(&out->lock);
2934
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002935 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2936 use_case_table[out->usecase],
2937 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2938
2939 if (status == CARD_STATUS_OFFLINE)
2940 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002941
2942 return;
2943}
2944
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002945#ifdef NO_AUDIO_OUT
2946static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002947 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002948{
2949 struct stream_out *out = (struct stream_out *)stream;
2950
2951 /* No Output device supported other than BT for playback.
2952 * Sleep for the amount of buffer duration
2953 */
Eric Laurenta1478072015-09-21 17:21:52 -07002954 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002955 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2956 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002957 out_get_sample_rate(&out->stream.common));
2958 pthread_mutex_unlock(&out->lock);
2959 return bytes;
2960}
2961#endif
2962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2964 size_t bytes)
2965{
2966 struct stream_out *out = (struct stream_out *)stream;
2967 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002968 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002969 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970
Eric Laurenta1478072015-09-21 17:21:52 -07002971 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002972 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002973 const size_t frame_size = audio_stream_out_frame_size(stream);
2974 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002975
Eric Laurent0e46adf2016-12-16 12:49:24 -08002976 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2977 error_code = ERROR_CODE_WRITE;
2978 goto exit;
2979 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002980
2981 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2982 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002983 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002984 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2985 ret = -EIO;
2986 goto exit;
2987 }
2988 }
2989 }
2990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002992 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002993 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002995
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002998 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002999 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 goto exit;
3001 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003002
vivek mehta40125092017-08-21 18:48:51 -07003003 // after standby always force set last known cal step
3004 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3005 ALOGD("%s: retry previous failed cal level set", __func__);
3006 send_gain_dep_calibration_l();
3007 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003010 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003011 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003012 if (out->send_new_metadata) {
3013 ALOGVV("send new gapless metadata");
3014 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3015 out->send_new_metadata = 0;
3016 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003017 unsigned int avail;
3018 struct timespec tstamp;
3019 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3020 /* Do not limit write size if the available frames count is unknown */
3021 if (ret != 0) {
3022 avail = bytes;
3023 }
3024 if (avail == 0) {
3025 ret = 0;
3026 } else {
3027 if (avail > bytes) {
3028 avail = bytes;
3029 }
3030 ret = compress_write(out->compr, buffer, avail);
3031 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3032 __func__, avail, ret);
3033 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003034
Eric Laurent6e895242013-09-05 16:10:57 -07003035 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3037 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003038 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039 compress_start(out->compr);
3040 out->playback_started = 1;
3041 out->offload_state = OFFLOAD_STATE_PLAYING;
3042 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003043 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003044 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003045 } else {
3046 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003047 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003049 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050 return ret;
3051 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003052 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003054 size_t bytes_to_write = bytes;
3055
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003056 if (out->muted)
3057 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003058 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003059 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003060 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3061 int16_t *src = (int16_t *)buffer;
3062 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003063
Eric Laurentad2dde92017-09-20 18:27:31 -07003064 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3065 out->format != AUDIO_FORMAT_PCM_16_BIT,
3066 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003067
Eric Laurentad2dde92017-09-20 18:27:31 -07003068 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3069 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3070 }
3071 bytes_to_write /= 2;
3072 }
3073 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3074
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003075 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003076 request_out_focus(out, ns);
3077
3078 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3079 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003080 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003081 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003082 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003083
Haynes Mathew George03c40102016-01-29 17:57:48 -08003084 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003085 } else {
3086 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 }
3089
3090exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003091 // For PCM we always consume the buffer and return #bytes regardless of ret.
3092 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003093 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003094 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003095 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003096
Andy Hung7401c7c2016-09-21 12:41:21 -07003097 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003098 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003099 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3100 ALOGE_IF(out->pcm != NULL,
3101 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003102 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003103 // usleep not guaranteed for values over 1 second but we don't limit here.
3104 }
3105 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107 pthread_mutex_unlock(&out->lock);
3108
3109 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003110 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003111 if (sleeptime_us != 0)
3112 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 }
3114 return bytes;
3115}
3116
3117static int out_get_render_position(const struct audio_stream_out *stream,
3118 uint32_t *dsp_frames)
3119{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 struct stream_out *out = (struct stream_out *)stream;
3121 *dsp_frames = 0;
3122 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003123 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003125 unsigned long frames = 0;
3126 // TODO: check return value
3127 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3128 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003129 ALOGVV("%s rendered frames %d sample_rate %d",
3130 __func__, *dsp_frames, out->sample_rate);
3131 }
3132 pthread_mutex_unlock(&out->lock);
3133 return 0;
3134 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003135 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136}
3137
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003138static int out_add_audio_effect(const struct audio_stream *stream __unused,
3139 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140{
3141 return 0;
3142}
3143
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003144static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3145 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146{
3147 return 0;
3148}
3149
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003150static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3151 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003153 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154}
3155
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003156static int out_get_presentation_position(const struct audio_stream_out *stream,
3157 uint64_t *frames, struct timespec *timestamp)
3158{
3159 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003160 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003161 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003162
Eric Laurenta1478072015-09-21 17:21:52 -07003163 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003164
Eric Laurent949a0892013-09-20 09:20:13 -07003165 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3166 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003167 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003168 compress_get_tstamp(out->compr, &dsp_frames,
3169 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003170 // Adjustment accounts for A2DP encoder latency with offload usecases
3171 // Note: Encoder latency is returned in ms.
3172 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3173 unsigned long offset =
3174 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3175 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3176 }
Eric Laurent949a0892013-09-20 09:20:13 -07003177 ALOGVV("%s rendered frames %ld sample_rate %d",
3178 __func__, dsp_frames, out->sample_rate);
3179 *frames = dsp_frames;
3180 ret = 0;
3181 /* this is the best we can do */
3182 clock_gettime(CLOCK_MONOTONIC, timestamp);
3183 }
3184 } else {
3185 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003186 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003187 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3188 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003189 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003190 // This adjustment accounts for buffering after app processor.
3191 // It is based on estimated DSP latency per use case, rather than exact.
3192 signed_frames -=
3193 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3194
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003195 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3196 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3197 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3198 signed_frames -=
3199 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3200 }
3201
Eric Laurent949a0892013-09-20 09:20:13 -07003202 // It would be unusual for this value to be negative, but check just in case ...
3203 if (signed_frames >= 0) {
3204 *frames = signed_frames;
3205 ret = 0;
3206 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003207 }
3208 }
3209 }
3210
3211 pthread_mutex_unlock(&out->lock);
3212
3213 return ret;
3214}
3215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003216static int out_set_callback(struct audio_stream_out *stream,
3217 stream_callback_t callback, void *cookie)
3218{
3219 struct stream_out *out = (struct stream_out *)stream;
3220
3221 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003222 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003223 out->offload_callback = callback;
3224 out->offload_cookie = cookie;
3225 pthread_mutex_unlock(&out->lock);
3226 return 0;
3227}
3228
3229static int out_pause(struct audio_stream_out* stream)
3230{
3231 struct stream_out *out = (struct stream_out *)stream;
3232 int status = -ENOSYS;
3233 ALOGV("%s", __func__);
3234 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003235 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3237 status = compress_pause(out->compr);
3238 out->offload_state = OFFLOAD_STATE_PAUSED;
3239 }
3240 pthread_mutex_unlock(&out->lock);
3241 }
3242 return status;
3243}
3244
3245static int out_resume(struct audio_stream_out* stream)
3246{
3247 struct stream_out *out = (struct stream_out *)stream;
3248 int status = -ENOSYS;
3249 ALOGV("%s", __func__);
3250 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3251 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003252 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3254 status = compress_resume(out->compr);
3255 out->offload_state = OFFLOAD_STATE_PLAYING;
3256 }
3257 pthread_mutex_unlock(&out->lock);
3258 }
3259 return status;
3260}
3261
3262static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3263{
3264 struct stream_out *out = (struct stream_out *)stream;
3265 int status = -ENOSYS;
3266 ALOGV("%s", __func__);
3267 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003268 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003269 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3270 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3271 else
3272 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3273 pthread_mutex_unlock(&out->lock);
3274 }
3275 return status;
3276}
3277
3278static int out_flush(struct audio_stream_out* stream)
3279{
3280 struct stream_out *out = (struct stream_out *)stream;
3281 ALOGV("%s", __func__);
3282 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003283 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003284 stop_compressed_output_l(out);
3285 pthread_mutex_unlock(&out->lock);
3286 return 0;
3287 }
3288 return -ENOSYS;
3289}
3290
Eric Laurent0e46adf2016-12-16 12:49:24 -08003291static int out_stop(const struct audio_stream_out* stream)
3292{
3293 struct stream_out *out = (struct stream_out *)stream;
3294 struct audio_device *adev = out->dev;
3295 int ret = -ENOSYS;
3296
3297 ALOGV("%s", __func__);
3298 pthread_mutex_lock(&adev->lock);
3299 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3300 out->playback_started && out->pcm != NULL) {
3301 pcm_stop(out->pcm);
3302 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003303 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003304 }
3305 pthread_mutex_unlock(&adev->lock);
3306 return ret;
3307}
3308
3309static int out_start(const struct audio_stream_out* stream)
3310{
3311 struct stream_out *out = (struct stream_out *)stream;
3312 struct audio_device *adev = out->dev;
3313 int ret = -ENOSYS;
3314
3315 ALOGV("%s", __func__);
3316 pthread_mutex_lock(&adev->lock);
3317 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3318 !out->playback_started && out->pcm != NULL) {
3319 ret = start_output_stream(out);
3320 if (ret == 0) {
3321 out->playback_started = true;
3322 }
3323 }
3324 pthread_mutex_unlock(&adev->lock);
3325 return ret;
3326}
3327
Phil Burkbc991042017-02-24 08:06:44 -08003328/*
3329 * Modify config->period_count based on min_size_frames
3330 */
3331static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3332{
3333 int periodCountRequested = (min_size_frames + config->period_size - 1)
3334 / config->period_size;
3335 int periodCount = MMAP_PERIOD_COUNT_MIN;
3336
3337 ALOGV("%s original config.period_size = %d config.period_count = %d",
3338 __func__, config->period_size, config->period_count);
3339
3340 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3341 periodCount *= 2;
3342 }
3343 config->period_count = periodCount;
3344
3345 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3346}
3347
Eric Laurent0e46adf2016-12-16 12:49:24 -08003348static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3349 int32_t min_size_frames,
3350 struct audio_mmap_buffer_info *info)
3351{
3352 struct stream_out *out = (struct stream_out *)stream;
3353 struct audio_device *adev = out->dev;
3354 int ret = 0;
3355 unsigned int offset1;
3356 unsigned int frames1;
3357 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003358 uint32_t mmap_size;
3359 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003360
3361 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003362 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003363 pthread_mutex_lock(&adev->lock);
3364
3365 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003366 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003367 ret = -EINVAL;
3368 goto exit;
3369 }
3370 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003371 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003372 ret = -ENOSYS;
3373 goto exit;
3374 }
3375 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3376 if (out->pcm_device_id < 0) {
3377 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3378 __func__, out->pcm_device_id, out->usecase);
3379 ret = -EINVAL;
3380 goto exit;
3381 }
Phil Burkbc991042017-02-24 08:06:44 -08003382
3383 adjust_mmap_period_count(&out->config, min_size_frames);
3384
Eric Laurent0e46adf2016-12-16 12:49:24 -08003385 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3386 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3387 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3388 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3389 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3390 step = "open";
3391 ret = -ENODEV;
3392 goto exit;
3393 }
3394 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3395 if (ret < 0) {
3396 step = "begin";
3397 goto exit;
3398 }
3399 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003400 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003401 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003402 ret = platform_get_mmap_data_fd(adev->platform,
3403 out->pcm_device_id, 0 /*playback*/,
3404 &info->shared_memory_fd,
3405 &mmap_size);
3406 if (ret < 0) {
3407 // Fall back to non exclusive mode
3408 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3409 } else {
3410 if (mmap_size < buffer_size) {
3411 step = "mmap";
3412 goto exit;
3413 }
3414 // FIXME: indicate exclusive mode support by returning a negative buffer size
3415 info->buffer_size_frames *= -1;
3416 }
3417 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003418
3419 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3420 if (ret < 0) {
3421 step = "commit";
3422 goto exit;
3423 }
Phil Burkbc991042017-02-24 08:06:44 -08003424
3425 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003426 ret = 0;
3427
3428 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3429 __func__, info->shared_memory_address, info->buffer_size_frames);
3430
3431exit:
3432 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003433 if (out->pcm == NULL) {
3434 ALOGE("%s: %s - %d", __func__, step, ret);
3435 } else {
3436 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003437 pcm_close(out->pcm);
3438 out->pcm = NULL;
3439 }
3440 }
3441 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003442 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003443 return ret;
3444}
3445
3446static int out_get_mmap_position(const struct audio_stream_out *stream,
3447 struct audio_mmap_position *position)
3448{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003449 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003450 struct stream_out *out = (struct stream_out *)stream;
3451 ALOGVV("%s", __func__);
3452 if (position == NULL) {
3453 return -EINVAL;
3454 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003455 lock_output_stream(out);
3456 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3457 out->pcm == NULL) {
3458 ret = -ENOSYS;
3459 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003460 }
3461
3462 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003463 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003464 if (ret < 0) {
3465 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003466 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003467 }
Andy Hungfc044e12017-03-20 09:24:22 -07003468 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003469exit:
3470 pthread_mutex_unlock(&out->lock);
3471 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003472}
3473
3474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475/** audio_stream_in implementation **/
3476static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3477{
3478 struct stream_in *in = (struct stream_in *)stream;
3479
3480 return in->config.rate;
3481}
3482
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003483static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484{
3485 return -ENOSYS;
3486}
3487
3488static size_t in_get_buffer_size(const struct audio_stream *stream)
3489{
3490 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003491 return in->config.period_size * in->af_period_multiplier *
3492 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003493}
3494
3495static uint32_t in_get_channels(const struct audio_stream *stream)
3496{
3497 struct stream_in *in = (struct stream_in *)stream;
3498
3499 return in->channel_mask;
3500}
3501
vivek mehta4ed66e62016-04-15 23:33:34 -07003502static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503{
vivek mehta4ed66e62016-04-15 23:33:34 -07003504 struct stream_in *in = (struct stream_in *)stream;
3505 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506}
3507
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003508static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509{
3510 return -ENOSYS;
3511}
3512
3513static int in_standby(struct audio_stream *stream)
3514{
3515 struct stream_in *in = (struct stream_in *)stream;
3516 struct audio_device *adev = in->dev;
3517 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003518 bool do_stop = true;
3519
Eric Laurent994a6932013-07-17 11:51:42 -07003520 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003521
3522 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003523
3524 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003525 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003526 audio_extn_sound_trigger_stop_lab(in);
3527 in->standby = true;
3528 }
3529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003531 if (adev->adm_deregister_stream)
3532 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3533
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003534 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003536 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003537 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003538 in->capture_started = false;
3539 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003540 if (in->pcm) {
3541 pcm_close(in->pcm);
3542 in->pcm = NULL;
3543 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003544 adev->enable_voicerx = false;
3545 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003546 if (do_stop) {
3547 status = stop_input_stream(in);
3548 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003549 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550 }
3551 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003552 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 return status;
3554}
3555
Andy Hungd13f0d32017-06-12 13:58:37 -07003556static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557{
Andy Hungd13f0d32017-06-12 13:58:37 -07003558 struct stream_in *in = (struct stream_in *)stream;
3559
3560 // We try to get the lock for consistency,
3561 // but it isn't necessary for these variables.
3562 // If we're not in standby, we may be blocked on a read.
3563 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3564 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3565 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3566 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3567
3568 if (locked) {
3569 pthread_mutex_unlock(&in->lock);
3570 }
3571
3572 // dump error info
3573 (void)error_log_dump(
3574 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 return 0;
3576}
3577
3578static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3579{
3580 struct stream_in *in = (struct stream_in *)stream;
3581 struct audio_device *adev = in->dev;
3582 struct str_parms *parms;
3583 char *str;
3584 char value[32];
3585 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003586 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587
Eric Laurent994a6932013-07-17 11:51:42 -07003588 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 parms = str_parms_create_str(kvpairs);
3590
3591 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3592
Eric Laurenta1478072015-09-21 17:21:52 -07003593 lock_input_stream(in);
3594
Eric Laurent150dbfe2013-02-27 14:31:02 -08003595 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596 if (ret >= 0) {
3597 val = atoi(value);
3598 /* no audio source uses val == 0 */
3599 if ((in->source != val) && (val != 0)) {
3600 in->source = val;
3601 }
3602 }
3603
3604 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 if (ret >= 0) {
3607 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003608 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003609
3610 // Workaround: If routing to an non existing usb device, fail gracefully
3611 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003612 int card;
3613 if (audio_is_usb_in_device(val) &&
3614 (card = get_alive_usb_card(parms)) >= 0) {
3615
3616 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003617 status = -ENOSYS;
3618 } else {
3619
3620 in->device = val;
3621 /* If recording is in progress, change the tx device to new device */
3622 if (!in->standby) {
3623 ALOGV("update input routing change");
3624 // inform adm before actual routing to prevent glitches.
3625 if (adev->adm_on_routing_change) {
3626 adev->adm_on_routing_change(adev->adm_data,
3627 in->capture_handle);
3628 }
3629 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003630 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 }
3633 }
3634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003636 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637
3638 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003639 ALOGV("%s: exit: status(%d)", __func__, status);
3640 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641}
3642
Haynes Mathew George569b7482017-05-08 14:44:27 -07003643static char* in_get_parameters(const struct audio_stream *stream,
3644 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003646 struct stream_in *in = (struct stream_in *)stream;
3647 struct str_parms *query = str_parms_create_str(keys);
3648 char *str;
3649 struct str_parms *reply = str_parms_create();
3650 bool replied = false;
3651
3652 ALOGV("%s: enter: keys - %s", __func__, keys);
3653 replied |= stream_get_parameter_channels(query, reply,
3654 &in->supported_channel_masks[0]);
3655 replied |= stream_get_parameter_formats(query, reply,
3656 &in->supported_formats[0]);
3657 replied |= stream_get_parameter_rates(query, reply,
3658 &in->supported_sample_rates[0]);
3659 if (replied) {
3660 str = str_parms_to_str(reply);
3661 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003662 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003663 }
3664 str_parms_destroy(query);
3665 str_parms_destroy(reply);
3666 ALOGV("%s: exit: returns - %s", __func__, str);
3667 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003668}
3669
Eric Laurent51f3c662018-04-10 18:21:34 -07003670static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671{
Eric Laurent51f3c662018-04-10 18:21:34 -07003672 struct stream_in *in = (struct stream_in *)stream;
3673 char mixer_ctl_name[128];
3674 struct mixer_ctl *ctl;
3675 int ctl_value;
3676
3677 ALOGV("%s: gain %f", __func__, gain);
3678
3679 if (stream == NULL)
3680 return -EINVAL;
3681
3682 /* in_set_gain() only used to silence MMAP capture for now */
3683 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3684 return -ENOSYS;
3685
3686 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3687
3688 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3689 if (!ctl) {
3690 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3691 __func__, mixer_ctl_name);
3692 return -ENOSYS;
3693 }
3694
3695 if (gain < RECORD_GAIN_MIN)
3696 gain = RECORD_GAIN_MIN;
3697 else if (gain > RECORD_GAIN_MAX)
3698 gain = RECORD_GAIN_MAX;
3699 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3700
3701 mixer_ctl_set_value(ctl, 0, ctl_value);
3702 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703}
3704
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003705static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3706{
3707 if (!stream || !parms)
3708 return;
3709
3710 struct stream_in *in = (struct stream_in *)stream;
3711 struct audio_device *adev = in->dev;
3712
3713 card_status_t status;
3714 int card;
3715 if (parse_snd_card_status(parms, &card, &status) < 0)
3716 return;
3717
3718 pthread_mutex_lock(&adev->lock);
3719 bool valid_cb = (card == adev->snd_card);
3720 pthread_mutex_unlock(&adev->lock);
3721
3722 if (!valid_cb)
3723 return;
3724
3725 lock_input_stream(in);
3726 if (in->card_status != status)
3727 in->card_status = status;
3728 pthread_mutex_unlock(&in->lock);
3729
3730 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3731 use_case_table[in->usecase],
3732 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3733
3734 // a better solution would be to report error back to AF and let
3735 // it put the stream to standby
3736 if (status == CARD_STATUS_OFFLINE)
3737 in_standby(&in->stream.common);
3738
3739 return;
3740}
3741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3743 size_t bytes)
3744{
3745 struct stream_in *in = (struct stream_in *)stream;
3746 struct audio_device *adev = in->dev;
3747 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003748 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003749 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750
Eric Laurenta1478072015-09-21 17:21:52 -07003751 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003752 const size_t frame_size = audio_stream_in_frame_size(stream);
3753 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003754
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003755 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003756 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003757 /* Read from sound trigger HAL */
3758 audio_extn_sound_trigger_read(in, buffer, bytes);
3759 pthread_mutex_unlock(&in->lock);
3760 return bytes;
3761 }
3762
Eric Laurent0e46adf2016-12-16 12:49:24 -08003763 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3764 ret = -ENOSYS;
3765 goto exit;
3766 }
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003769 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003771 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 goto exit;
3774 }
3775 in->standby = 0;
3776 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777
Andy Hungd13f0d32017-06-12 13:58:37 -07003778 // errors that occur here are read errors.
3779 error_code = ERROR_CODE_READ;
3780
Haynes Mathew George03c40102016-01-29 17:57:48 -08003781 //what's the duration requested by the client?
3782 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3783 in->config.rate;
3784 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003785
Haynes Mathew George03c40102016-01-29 17:57:48 -08003786 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003788 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003789 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003790 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003791 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003792 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003793 if (ret < 0) {
3794 ALOGE("Failed to read w/err %s", strerror(errno));
3795 ret = -errno;
3796 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003797 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3798 if (bytes % 4 == 0) {
3799 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3800 int_buf_stream = buffer;
3801 for (size_t itt=0; itt < bytes/4 ; itt++) {
3802 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003803 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003804 } else {
3805 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3806 ret = -EINVAL;
3807 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003808 }
3809 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 }
3811
Haynes Mathew George03c40102016-01-29 17:57:48 -08003812 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 /*
3815 * Instead of writing zeroes here, we could trust the hardware
3816 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003817 * 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 -08003818 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003819 if (ret == 0 && adev->mic_muted &&
3820 !voice_is_in_call_rec_stream(in) &&
3821 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003823 in->frames_muted += frames;
3824 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825
3826exit:
3827 pthread_mutex_unlock(&in->lock);
3828
3829 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003830 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831 in_standby(&in->stream.common);
3832 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003833 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003834 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003835 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003836 }
3837 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003838 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 }
3840 return bytes;
3841}
3842
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003843static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844{
3845 return 0;
3846}
3847
Andy Hung6ebe5962016-01-15 17:46:57 -08003848static int in_get_capture_position(const struct audio_stream_in *stream,
3849 int64_t *frames, int64_t *time)
3850{
3851 if (stream == NULL || frames == NULL || time == NULL) {
3852 return -EINVAL;
3853 }
3854 struct stream_in *in = (struct stream_in *)stream;
3855 int ret = -ENOSYS;
3856
3857 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003858 // note: ST sessions do not close the alsa pcm driver synchronously
3859 // on standby. Therefore, we may return an error even though the
3860 // pcm stream is still opened.
3861 if (in->standby) {
3862 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3863 "%s stream in standby but pcm not NULL for non ST session", __func__);
3864 goto exit;
3865 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003866 if (in->pcm) {
3867 struct timespec timestamp;
3868 unsigned int avail;
3869 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3870 *frames = in->frames_read + avail;
3871 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3872 ret = 0;
3873 }
3874 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003875exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003876 pthread_mutex_unlock(&in->lock);
3877 return ret;
3878}
3879
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003880static int add_remove_audio_effect(const struct audio_stream *stream,
3881 effect_handle_t effect,
3882 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003884 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003885 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003886 int status = 0;
3887 effect_descriptor_t desc;
3888
3889 status = (*effect)->get_descriptor(effect, &desc);
3890 if (status != 0)
3891 return status;
3892
Eric Laurenta1478072015-09-21 17:21:52 -07003893 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003894 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003895 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003896 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003897 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003898 in->enable_aec != enable &&
3899 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3900 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003901 if (!enable)
3902 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003903 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3904 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3905 adev->enable_voicerx = enable;
3906 struct audio_usecase *usecase;
3907 struct listnode *node;
3908 list_for_each(node, &adev->usecase_list) {
3909 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003910 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003911 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003912 }
3913 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003914 if (!in->standby)
3915 select_devices(in->dev, in->usecase);
3916 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003917 if (in->enable_ns != enable &&
3918 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3919 in->enable_ns = enable;
3920 if (!in->standby)
3921 select_devices(in->dev, in->usecase);
3922 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003923 pthread_mutex_unlock(&in->dev->lock);
3924 pthread_mutex_unlock(&in->lock);
3925
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003926 return 0;
3927}
3928
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003929static int in_add_audio_effect(const struct audio_stream *stream,
3930 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931{
Eric Laurent994a6932013-07-17 11:51:42 -07003932 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003933 return add_remove_audio_effect(stream, effect, true);
3934}
3935
3936static int in_remove_audio_effect(const struct audio_stream *stream,
3937 effect_handle_t effect)
3938{
Eric Laurent994a6932013-07-17 11:51:42 -07003939 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003940 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941}
3942
Eric Laurent0e46adf2016-12-16 12:49:24 -08003943static int in_stop(const struct audio_stream_in* stream)
3944{
3945 struct stream_in *in = (struct stream_in *)stream;
3946 struct audio_device *adev = in->dev;
3947
3948 int ret = -ENOSYS;
3949 ALOGV("%s", __func__);
3950 pthread_mutex_lock(&adev->lock);
3951 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3952 in->capture_started && in->pcm != NULL) {
3953 pcm_stop(in->pcm);
3954 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003955 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003956 }
3957 pthread_mutex_unlock(&adev->lock);
3958 return ret;
3959}
3960
3961static int in_start(const struct audio_stream_in* stream)
3962{
3963 struct stream_in *in = (struct stream_in *)stream;
3964 struct audio_device *adev = in->dev;
3965 int ret = -ENOSYS;
3966
3967 ALOGV("%s in %p", __func__, in);
3968 pthread_mutex_lock(&adev->lock);
3969 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3970 !in->capture_started && in->pcm != NULL) {
3971 if (!in->capture_started) {
3972 ret = start_input_stream(in);
3973 if (ret == 0) {
3974 in->capture_started = true;
3975 }
3976 }
3977 }
3978 pthread_mutex_unlock(&adev->lock);
3979 return ret;
3980}
3981
3982static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3983 int32_t min_size_frames,
3984 struct audio_mmap_buffer_info *info)
3985{
3986 struct stream_in *in = (struct stream_in *)stream;
3987 struct audio_device *adev = in->dev;
3988 int ret = 0;
3989 unsigned int offset1;
3990 unsigned int frames1;
3991 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003992 uint32_t mmap_size;
3993 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003994
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003995 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003996 pthread_mutex_lock(&adev->lock);
3997 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003998
Eric Laurent0e46adf2016-12-16 12:49:24 -08003999 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004000 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004001 ret = -EINVAL;
4002 goto exit;
4003 }
4004 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004005 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004006 ALOGV("%s in %p", __func__, in);
4007 ret = -ENOSYS;
4008 goto exit;
4009 }
4010 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4011 if (in->pcm_device_id < 0) {
4012 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4013 __func__, in->pcm_device_id, in->usecase);
4014 ret = -EINVAL;
4015 goto exit;
4016 }
Phil Burkbc991042017-02-24 08:06:44 -08004017
4018 adjust_mmap_period_count(&in->config, min_size_frames);
4019
Eric Laurent0e46adf2016-12-16 12:49:24 -08004020 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4021 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4022 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4023 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4024 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4025 step = "open";
4026 ret = -ENODEV;
4027 goto exit;
4028 }
4029
4030 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4031 if (ret < 0) {
4032 step = "begin";
4033 goto exit;
4034 }
4035 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004036 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004037 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004038 ret = platform_get_mmap_data_fd(adev->platform,
4039 in->pcm_device_id, 1 /*capture*/,
4040 &info->shared_memory_fd,
4041 &mmap_size);
4042 if (ret < 0) {
4043 // Fall back to non exclusive mode
4044 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4045 } else {
4046 if (mmap_size < buffer_size) {
4047 step = "mmap";
4048 goto exit;
4049 }
4050 // FIXME: indicate exclusive mode support by returning a negative buffer size
4051 info->buffer_size_frames *= -1;
4052 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004053
Haynes Mathew George96483a22017-03-28 14:52:47 -07004054 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004055
4056 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4057 if (ret < 0) {
4058 step = "commit";
4059 goto exit;
4060 }
4061
Phil Burkbc991042017-02-24 08:06:44 -08004062 in->standby = false;
4063 ret = 0;
4064
Eric Laurent0e46adf2016-12-16 12:49:24 -08004065 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4066 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004067
4068exit:
4069 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004070 if (in->pcm == NULL) {
4071 ALOGE("%s: %s - %d", __func__, step, ret);
4072 } else {
4073 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004074 pcm_close(in->pcm);
4075 in->pcm = NULL;
4076 }
4077 }
4078 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004079 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004080 return ret;
4081}
4082
4083static int in_get_mmap_position(const struct audio_stream_in *stream,
4084 struct audio_mmap_position *position)
4085{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004086 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004087 struct stream_in *in = (struct stream_in *)stream;
4088 ALOGVV("%s", __func__);
4089 if (position == NULL) {
4090 return -EINVAL;
4091 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004092 lock_input_stream(in);
4093 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4094 in->pcm == NULL) {
4095 ret = -ENOSYS;
4096 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004097 }
4098 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004099 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004100 if (ret < 0) {
4101 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004102 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004103 }
Andy Hungfc044e12017-03-20 09:24:22 -07004104 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004105exit:
4106 pthread_mutex_unlock(&in->lock);
4107 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004108}
4109
jiabin8962a4d2018-03-19 18:21:24 -07004110static int in_get_active_microphones(const struct audio_stream_in *stream,
4111 struct audio_microphone_characteristic_t *mic_array,
4112 size_t *mic_count) {
4113 struct stream_in *in = (struct stream_in *)stream;
4114 struct audio_device *adev = in->dev;
4115 ALOGVV("%s", __func__);
4116
4117 lock_input_stream(in);
4118 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004119 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004120 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004121 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004122 pthread_mutex_unlock(&adev->lock);
4123 pthread_mutex_unlock(&in->lock);
4124
4125 return ret;
4126}
4127
4128static int adev_get_microphones(const struct audio_hw_device *dev,
4129 struct audio_microphone_characteristic_t *mic_array,
4130 size_t *mic_count) {
4131 struct audio_device *adev = (struct audio_device *)dev;
4132 ALOGVV("%s", __func__);
4133
4134 pthread_mutex_lock(&adev->lock);
4135 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4136 pthread_mutex_unlock(&adev->lock);
4137
4138 return ret;
4139}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141static int adev_open_output_stream(struct audio_hw_device *dev,
4142 audio_io_handle_t handle,
4143 audio_devices_t devices,
4144 audio_output_flags_t flags,
4145 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004146 struct audio_stream_out **stream_out,
4147 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148{
4149 struct audio_device *adev = (struct audio_device *)dev;
4150 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004151 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004152 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4153 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4154 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155
Andy Hungd9653bd2017-08-01 19:31:39 -07004156 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4157 return -ENOSYS;
4158 }
4159
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004160 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4161 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 *stream_out = NULL;
4163 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4164
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004165 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167 if (devices == AUDIO_DEVICE_NONE)
4168 devices = AUDIO_DEVICE_OUT_SPEAKER;
4169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 out->flags = flags;
4171 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004172 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004173 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004174 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175
4176 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004177 if ((is_hdmi || is_usb_dev) &&
4178 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4179 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4180 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004181 audio_format_t req_format = config->format;
4182 audio_channel_mask_t req_channel_mask = config->channel_mask;
4183 uint32_t req_sample_rate = config->sample_rate;
4184
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004185 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004186 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004187 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004188 if (config->sample_rate == 0)
4189 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004190 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004191 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4192 if (config->format == AUDIO_FORMAT_DEFAULT)
4193 config->format = AUDIO_FORMAT_PCM_16_BIT;
4194 } else if (is_usb_dev) {
4195 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4196 &config->format,
4197 &out->supported_formats[0],
4198 MAX_SUPPORTED_FORMATS,
4199 &config->channel_mask,
4200 &out->supported_channel_masks[0],
4201 MAX_SUPPORTED_CHANNEL_MASKS,
4202 &config->sample_rate,
4203 &out->supported_sample_rates[0],
4204 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004205 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004206 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004207 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004208 if (ret != 0) {
4209 // For MMAP NO IRQ, allow conversions in ADSP
4210 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4211 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004212
Eric Laurentab805ee2018-03-30 12:20:38 -07004213 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4214 config->sample_rate = req_sample_rate;
4215 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4216 config->channel_mask = req_channel_mask;
4217 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4218 config->format = req_format;
4219 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004220
Haynes Mathew George569b7482017-05-08 14:44:27 -07004221 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004222 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004223 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004224 if (is_hdmi) {
4225 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4226 out->config = pcm_config_hdmi_multi;
4227 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4228 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4229 out->config = pcm_config_mmap_playback;
4230 out->stream.start = out_start;
4231 out->stream.stop = out_stop;
4232 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4233 out->stream.get_mmap_position = out_get_mmap_position;
4234 } else {
4235 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4236 out->config = pcm_config_hifi;
4237 }
4238
4239 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004240 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004241 if (is_hdmi) {
4242 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4243 audio_bytes_per_sample(out->format));
4244 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004245 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004246 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004247 pthread_mutex_lock(&adev->lock);
4248 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4249 pthread_mutex_unlock(&adev->lock);
4250
4251 // reject offload during card offline to allow
4252 // fallback to s/w paths
4253 if (offline) {
4254 ret = -ENODEV;
4255 goto error_open;
4256 }
4257
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004258 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4259 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4260 ALOGE("%s: Unsupported Offload information", __func__);
4261 ret = -EINVAL;
4262 goto error_open;
4263 }
4264 if (!is_supported_format(config->offload_info.format)) {
4265 ALOGE("%s: Unsupported audio format", __func__);
4266 ret = -EINVAL;
4267 goto error_open;
4268 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004269 out->sample_rate = config->offload_info.sample_rate;
4270 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4271 out->channel_mask = config->offload_info.channel_mask;
4272 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4273 out->channel_mask = config->channel_mask;
4274 else
4275 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4276
4277 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004278
4279 out->compr_config.codec = (struct snd_codec *)
4280 calloc(1, sizeof(struct snd_codec));
4281
4282 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004283
4284 out->stream.set_callback = out_set_callback;
4285 out->stream.pause = out_pause;
4286 out->stream.resume = out_resume;
4287 out->stream.drain = out_drain;
4288 out->stream.flush = out_flush;
4289
4290 out->compr_config.codec->id =
4291 get_snd_codec_id(config->offload_info.format);
4292 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4293 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004294 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004295 out->compr_config.codec->bit_rate =
4296 config->offload_info.bit_rate;
4297 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004298 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004299 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4300
4301 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4302 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004303
4304 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004305 create_offload_callback_thread(out);
4306 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4307 __func__, config->offload_info.version,
4308 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004309 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4310 switch (config->sample_rate) {
4311 case 0:
4312 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4313 break;
4314 case 8000:
4315 case 16000:
4316 case 48000:
4317 out->sample_rate = config->sample_rate;
4318 break;
4319 default:
4320 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4321 config->sample_rate);
4322 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4323 ret = -EINVAL;
4324 goto error_open;
4325 }
4326 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4327 switch (config->channel_mask) {
4328 case AUDIO_CHANNEL_NONE:
4329 case AUDIO_CHANNEL_OUT_STEREO:
4330 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4331 break;
4332 default:
4333 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4334 config->channel_mask);
4335 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4336 ret = -EINVAL;
4337 goto error_open;
4338 }
4339 switch (config->format) {
4340 case AUDIO_FORMAT_DEFAULT:
4341 case AUDIO_FORMAT_PCM_16_BIT:
4342 out->format = AUDIO_FORMAT_PCM_16_BIT;
4343 break;
4344 default:
4345 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4346 config->format);
4347 config->format = AUDIO_FORMAT_PCM_16_BIT;
4348 ret = -EINVAL;
4349 goto error_open;
4350 }
4351
4352 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004353 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004354 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004355 case 0:
4356 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4357 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004358 case 8000:
4359 case 16000:
4360 case 48000:
4361 out->sample_rate = config->sample_rate;
4362 break;
4363 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004364 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4365 config->sample_rate);
4366 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4367 ret = -EINVAL;
4368 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004369 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004370 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4371 switch (config->channel_mask) {
4372 case AUDIO_CHANNEL_NONE:
4373 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4374 break;
4375 case AUDIO_CHANNEL_OUT_STEREO:
4376 out->channel_mask = config->channel_mask;
4377 break;
4378 default:
4379 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4380 config->channel_mask);
4381 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4382 ret = -EINVAL;
4383 break;
4384 }
4385 switch (config->format) {
4386 case AUDIO_FORMAT_DEFAULT:
4387 out->format = AUDIO_FORMAT_PCM_16_BIT;
4388 break;
4389 case AUDIO_FORMAT_PCM_16_BIT:
4390 out->format = config->format;
4391 break;
4392 default:
4393 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4394 config->format);
4395 config->format = AUDIO_FORMAT_PCM_16_BIT;
4396 ret = -EINVAL;
4397 break;
4398 }
4399 if (ret != 0)
4400 goto error_open;
4401
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004402 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4403 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004404 out->config.rate = out->sample_rate;
4405 out->config.channels =
4406 audio_channel_count_from_out_mask(out->channel_mask);
4407 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004408 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004409 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4410 switch (config->sample_rate) {
4411 case 0:
4412 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4413 break;
4414 case 8000:
4415 case 16000:
4416 case 32000:
4417 case 48000:
4418 out->sample_rate = config->sample_rate;
4419 break;
4420 default:
4421 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4422 config->sample_rate);
4423 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4424 ret = -EINVAL;
4425 break;
4426 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004427 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004428 switch (config->channel_mask) {
4429 case AUDIO_CHANNEL_NONE:
4430 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4431 break;
4432 case AUDIO_CHANNEL_OUT_STEREO:
4433 out->channel_mask = config->channel_mask;
4434 break;
4435 default:
4436 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4437 config->channel_mask);
4438 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4439 ret = -EINVAL;
4440 break;
4441 }
4442 switch (config->format) {
4443 case AUDIO_FORMAT_DEFAULT:
4444 out->format = AUDIO_FORMAT_PCM_16_BIT;
4445 break;
4446 case AUDIO_FORMAT_PCM_16_BIT:
4447 out->format = config->format;
4448 break;
4449 default:
4450 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4451 config->format);
4452 config->format = AUDIO_FORMAT_PCM_16_BIT;
4453 ret = -EINVAL;
4454 break;
4455 }
4456 if (ret != 0)
4457 goto error_open;
4458
vivek mehtaa68fea62017-06-08 19:04:02 -07004459 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004460 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4461 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004462 out->config.rate = out->sample_rate;
4463 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004464 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004465 out->sample_rate,
4466 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004467 out->config.channels,
4468 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004469 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004470 out->config.period_size = buffer_size / frame_size;
4471 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4472 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004474 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004475 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4476 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004477 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004478 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4479 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004480 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004481 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004482 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004483 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004484 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004485 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4486 out->config = pcm_config_mmap_playback;
4487 out->stream.start = out_start;
4488 out->stream.stop = out_stop;
4489 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4490 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004491 } else {
4492 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4493 out->config = pcm_config_low_latency;
4494 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004495
4496 if (config->sample_rate == 0) {
4497 out->sample_rate = out->config.rate;
4498 } else {
4499 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004500 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004501 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4502 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4503 } else {
4504 out->channel_mask = config->channel_mask;
4505 }
4506 if (config->format == AUDIO_FORMAT_DEFAULT)
4507 out->format = audio_format_from_pcm_format(out->config.format);
4508 else if (!audio_is_linear_pcm(config->format)) {
4509 config->format = AUDIO_FORMAT_PCM_16_BIT;
4510 ret = -EINVAL;
4511 goto error_open;
4512 } else {
4513 out->format = config->format;
4514 }
4515
4516 out->config.rate = out->sample_rate;
4517 out->config.channels =
4518 audio_channel_count_from_out_mask(out->channel_mask);
4519 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4520 out->config.format = pcm_format_from_audio_format(out->format);
4521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004523
4524 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4525 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004526 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004527 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4528 __func__, config->sample_rate, config->format, config->channel_mask);
4529 config->sample_rate = out->sample_rate;
4530 config->format = out->format;
4531 config->channel_mask = out->channel_mask;
4532 ret = -EINVAL;
4533 goto error_open;
4534 }
4535
Andy Hung6fcba9c2014-03-18 11:53:32 -07004536 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4537 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004539 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004540 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004541 adev->primary_output = out;
4542 else {
4543 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004544 ret = -EEXIST;
4545 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004546 }
4547 }
4548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004549 /* Check if this usecase is already existing */
4550 pthread_mutex_lock(&adev->lock);
4551 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4552 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004554 ret = -EEXIST;
4555 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556 }
4557 pthread_mutex_unlock(&adev->lock);
4558
4559 out->stream.common.get_sample_rate = out_get_sample_rate;
4560 out->stream.common.set_sample_rate = out_set_sample_rate;
4561 out->stream.common.get_buffer_size = out_get_buffer_size;
4562 out->stream.common.get_channels = out_get_channels;
4563 out->stream.common.get_format = out_get_format;
4564 out->stream.common.set_format = out_set_format;
4565 out->stream.common.standby = out_standby;
4566 out->stream.common.dump = out_dump;
4567 out->stream.common.set_parameters = out_set_parameters;
4568 out->stream.common.get_parameters = out_get_parameters;
4569 out->stream.common.add_audio_effect = out_add_audio_effect;
4570 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4571 out->stream.get_latency = out_get_latency;
4572 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004573#ifdef NO_AUDIO_OUT
4574 out->stream.write = out_write_for_no_output;
4575#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004577#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578 out->stream.get_render_position = out_get_render_position;
4579 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004580 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004581
Eric Laurent0e46adf2016-12-16 12:49:24 -08004582 if (out->realtime)
4583 out->af_period_multiplier = af_period_multiplier;
4584 else
4585 out->af_period_multiplier = 1;
4586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004588 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004589 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004591 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004592 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004593 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595 config->format = out->stream.common.get_format(&out->stream.common);
4596 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4597 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4598
Kevin Rocarda325aa22018-04-03 09:15:52 -07004599 register_format(out->format, out->supported_formats);
4600 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4601 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4602
Andy Hunga452b0a2017-03-15 14:51:15 -07004603 out->error_log = error_log_create(
4604 ERROR_LOG_ENTRIES,
4605 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4606
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004607 /*
4608 By locking output stream before registering, we allow the callback
4609 to update stream's state only after stream's initial state is set to
4610 adev state.
4611 */
4612 lock_output_stream(out);
4613 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4614 pthread_mutex_lock(&adev->lock);
4615 out->card_status = adev->card_status;
4616 pthread_mutex_unlock(&adev->lock);
4617 pthread_mutex_unlock(&out->lock);
4618
vivek mehta4a824772017-06-08 19:05:49 -07004619 stream_app_type_cfg_init(&out->app_type_cfg);
4620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004622
Eric Laurent994a6932013-07-17 11:51:42 -07004623 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004625
4626error_open:
4627 free(out);
4628 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004629 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004630 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631}
4632
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004633static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 struct audio_stream_out *stream)
4635{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004636 struct stream_out *out = (struct stream_out *)stream;
4637 struct audio_device *adev = out->dev;
4638
Eric Laurent994a6932013-07-17 11:51:42 -07004639 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004640
4641 // must deregister from sndmonitor first to prevent races
4642 // between the callback and close_stream
4643 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004645 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4646 destroy_offload_callback_thread(out);
4647
4648 if (out->compr_config.codec != NULL)
4649 free(out->compr_config.codec);
4650 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004651
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004652 out->a2dp_compress_mute = false;
4653
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004654 if (adev->voice_tx_output == out)
4655 adev->voice_tx_output = NULL;
4656
Andy Hunga452b0a2017-03-15 14:51:15 -07004657 error_log_destroy(out->error_log);
4658 out->error_log = NULL;
4659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004660 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004661 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004662 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004664 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004665}
4666
4667static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4668{
4669 struct audio_device *adev = (struct audio_device *)dev;
4670 struct str_parms *parms;
4671 char *str;
4672 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004673 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004675 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004676 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677
Joe Onorato188b6222016-03-01 11:02:27 -08004678 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004679
4680 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681
4682 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004683 status = voice_set_parameters(adev, parms);
4684 if (status != 0) {
4685 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686 }
4687
4688 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4689 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004690 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4692 adev->bluetooth_nrec = true;
4693 else
4694 adev->bluetooth_nrec = false;
4695 }
4696
4697 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4698 if (ret >= 0) {
4699 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4700 adev->screen_off = false;
4701 else
4702 adev->screen_off = true;
4703 }
4704
jasmine cha270b7762018-03-30 15:41:33 +08004705#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004706 ret = str_parms_get_int(parms, "rotation", &val);
4707 if (ret >= 0) {
4708 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004709 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004710 // FIXME: note that the code below assumes that the speakers are in the correct placement
4711 // relative to the user when the device is rotated 90deg from its default rotation. This
4712 // assumption is device-specific, not platform-specific like this code.
4713 case 270:
4714 reverse_speakers = true;
4715 break;
4716 case 0:
4717 case 90:
4718 case 180:
4719 break;
4720 default:
4721 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004722 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004723 }
Eric Laurent03f09432014-03-25 18:09:11 -07004724 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004725 // check and set swap
4726 // - check if orientation changed and speaker active
4727 // - set rotation and cache the rotation value
4728 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004729 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004730 }
jasmine cha270b7762018-03-30 15:41:33 +08004731#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004732
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004733 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4734 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004735 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004736 }
4737
David Linee3fe402017-03-13 10:00:42 -07004738 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4739 if (ret >= 0) {
4740 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004741 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004742 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4743 if (ret >= 0) {
4744 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004745 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004746 }
Eric Laurent99dab492017-06-17 15:19:08 -07004747 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004748 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4749 if (ret >= 0) {
4750 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004751 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004752 }
4753 }
4754 }
4755
4756 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4757 if (ret >= 0) {
4758 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004759 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004760 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4761 if (ret >= 0) {
4762 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004763 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004764 }
Eric Laurent99dab492017-06-17 15:19:08 -07004765 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004766 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4767 if (ret >= 0) {
4768 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004769 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004770 }
4771 }
4772 }
4773
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004774 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004775 audio_extn_ma_set_parameters(adev, parms);
4776
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004777 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4778 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004779 struct audio_usecase *usecase;
4780 struct listnode *node;
4781 list_for_each(node, &adev->usecase_list) {
4782 usecase = node_to_item(node, struct audio_usecase, list);
4783 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004784 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004785 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4786
4787 pthread_mutex_unlock(&adev->lock);
4788 lock_output_stream(usecase->stream.out);
4789 pthread_mutex_lock(&adev->lock);
4790 audio_extn_a2dp_set_handoff_mode(true);
4791 // force device switch to reconfigure encoder
4792 select_devices(adev, usecase->id);
4793 audio_extn_a2dp_set_handoff_mode(false);
4794 pthread_mutex_unlock(&usecase->stream.out->lock);
4795 break;
4796 }
4797 }
4798 }
4799
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004800done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004802 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004803 ALOGV("%s: exit with code(%d)", __func__, status);
4804 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805}
4806
4807static char* adev_get_parameters(const struct audio_hw_device *dev,
4808 const char *keys)
4809{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004810 struct audio_device *adev = (struct audio_device *)dev;
4811 struct str_parms *reply = str_parms_create();
4812 struct str_parms *query = str_parms_create_str(keys);
4813 char *str;
4814
4815 pthread_mutex_lock(&adev->lock);
4816
4817 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004818 audio_extn_a2dp_get_parameters(query, reply);
4819
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004820 str = str_parms_to_str(reply);
4821 str_parms_destroy(query);
4822 str_parms_destroy(reply);
4823
4824 pthread_mutex_unlock(&adev->lock);
4825 ALOGV("%s: exit: returns - %s", __func__, str);
4826 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827}
4828
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004829static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830{
4831 return 0;
4832}
4833
Haynes Mathew George5191a852013-09-11 14:19:36 -07004834static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4835{
4836 int ret;
4837 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004838
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004839 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4840
Haynes Mathew George5191a852013-09-11 14:19:36 -07004841 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004842 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004843 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004844
Haynes Mathew George5191a852013-09-11 14:19:36 -07004845 return ret;
4846}
4847
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004848static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849{
4850 return -ENOSYS;
4851}
4852
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004853static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4854 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004855{
4856 return -ENOSYS;
4857}
4858
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004859static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860{
4861 return -ENOSYS;
4862}
4863
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004864static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004865{
4866 return -ENOSYS;
4867}
4868
4869static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4870{
4871 struct audio_device *adev = (struct audio_device *)dev;
4872
4873 pthread_mutex_lock(&adev->lock);
4874 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004875 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004877 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4878 voice_is_in_call(adev)) {
4879 voice_stop_call(adev);
4880 adev->current_call_output = NULL;
4881 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004882 }
4883 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004884
4885 audio_extn_extspk_set_mode(adev->extspk, mode);
4886
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887 return 0;
4888}
4889
4890static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4891{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004892 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894
Eric Laurent2bafff12016-03-17 12:17:23 -07004895 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004896 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004897 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4898 ret = audio_extn_hfp_set_mic_mute(adev, state);
4899 } else {
4900 ret = voice_set_mic_mute(adev, state);
4901 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004902 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004903 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004904
4905 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004906}
4907
4908static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4909{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004910 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911 return 0;
4912}
4913
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004914static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004915 const struct audio_config *config)
4916{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004917 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918
Eric Laurent74b55762017-07-09 17:04:53 -07004919 /* Don't know if USB HIFI in this context so use true to be conservative */
4920 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4921 true /*is_usb_hifi */) != 0)
4922 return 0;
4923
vivek mehtaa68fea62017-06-08 19:04:02 -07004924 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4925 config->sample_rate, config->format,
4926 channel_count,
4927 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928}
4929
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004930static bool adev_input_allow_hifi_record(struct audio_device *adev,
4931 audio_devices_t devices,
4932 audio_input_flags_t flags,
4933 audio_source_t source) {
4934 const bool allowed = true;
4935
4936 if (!audio_is_usb_in_device(devices))
4937 return !allowed;
4938
4939 switch (flags) {
4940 case AUDIO_INPUT_FLAG_NONE:
4941 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4942 break;
4943 default:
4944 return !allowed;
4945 }
4946
4947 switch (source) {
4948 case AUDIO_SOURCE_DEFAULT:
4949 case AUDIO_SOURCE_MIC:
4950 case AUDIO_SOURCE_UNPROCESSED:
4951 break;
4952 default:
4953 return !allowed;
4954 }
4955
4956 switch (adev->mode) {
4957 case 0:
4958 break;
4959 default:
4960 return !allowed;
4961 }
4962
4963 return allowed;
4964}
4965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004967 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004968 audio_devices_t devices,
4969 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004970 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004971 audio_input_flags_t flags,
4972 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004973 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974{
4975 struct audio_device *adev = (struct audio_device *)dev;
4976 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004977 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004978 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004979 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004980 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004981 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4982 devices,
4983 flags,
4984 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004985 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004986 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004987
Andy Hungd9653bd2017-08-01 19:31:39 -07004988 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4989 return -ENOSYS;
4990 }
4991
Eric Laurent74b55762017-07-09 17:04:53 -07004992 if (!(is_usb_dev && may_use_hifi_record)) {
4993 if (config->sample_rate == 0)
4994 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4995 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4996 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4997 if (config->format == AUDIO_FORMAT_DEFAULT)
4998 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004999
Eric Laurent74b55762017-07-09 17:04:53 -07005000 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5001
5002 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5003 return -EINVAL;
5004 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005006 if (audio_extn_tfa_98xx_is_supported() &&
5007 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005008 return -EINVAL;
5009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005010 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5011
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005012 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005013 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015 in->stream.common.get_sample_rate = in_get_sample_rate;
5016 in->stream.common.set_sample_rate = in_set_sample_rate;
5017 in->stream.common.get_buffer_size = in_get_buffer_size;
5018 in->stream.common.get_channels = in_get_channels;
5019 in->stream.common.get_format = in_get_format;
5020 in->stream.common.set_format = in_set_format;
5021 in->stream.common.standby = in_standby;
5022 in->stream.common.dump = in_dump;
5023 in->stream.common.set_parameters = in_set_parameters;
5024 in->stream.common.get_parameters = in_get_parameters;
5025 in->stream.common.add_audio_effect = in_add_audio_effect;
5026 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5027 in->stream.set_gain = in_set_gain;
5028 in->stream.read = in_read;
5029 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005030 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005031 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005032
5033 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005034 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005035 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005037 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005038 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005040 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5041 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5042 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5043 /* Force channel config requested to mono if incall
5044 record is being requested for only uplink/downlink */
5045 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5046 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5047 ret = -EINVAL;
5048 goto err_open;
5049 }
5050 }
5051
Haynes Mathew George569b7482017-05-08 14:44:27 -07005052 if (is_usb_dev && may_use_hifi_record) {
5053 /* HiFi record selects an appropriate format, channel, rate combo
5054 depending on sink capabilities*/
5055 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5056 &config->format,
5057 &in->supported_formats[0],
5058 MAX_SUPPORTED_FORMATS,
5059 &config->channel_mask,
5060 &in->supported_channel_masks[0],
5061 MAX_SUPPORTED_CHANNEL_MASKS,
5062 &config->sample_rate,
5063 &in->supported_sample_rates[0],
5064 MAX_SUPPORTED_SAMPLE_RATES);
5065 if (ret != 0) {
5066 ret = -EINVAL;
5067 goto err_open;
5068 }
Eric Laurent74b55762017-07-09 17:04:53 -07005069 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005070 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005071 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005072 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5073 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5074 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5075 bool ret_error = false;
5076 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5077 from HAL is 8_24
5078 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5079 8_24 return error indicating supported format is 8_24
5080 *> In case of any other source requesting 24 bit or float return error
5081 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005082
vivek mehta57ff9b52016-04-28 14:13:08 -07005083 on error flinger will retry with supported format passed
5084 */
5085 if (source != AUDIO_SOURCE_UNPROCESSED) {
5086 config->format = AUDIO_FORMAT_PCM_16_BIT;
5087 ret_error = true;
5088 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5089 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5090 ret_error = true;
5091 }
5092
5093 if (ret_error) {
5094 ret = -EINVAL;
5095 goto err_open;
5096 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005097 }
5098
vivek mehta57ff9b52016-04-28 14:13:08 -07005099 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005100 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005102 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005103 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5104 if (config->sample_rate == 0)
5105 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5106 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5107 config->sample_rate != 8000) {
5108 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5109 ret = -EINVAL;
5110 goto err_open;
5111 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005112
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005113 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5114 config->format = AUDIO_FORMAT_PCM_16_BIT;
5115 ret = -EINVAL;
5116 goto err_open;
5117 }
5118
5119 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5120 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005121 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005122 } else if (is_usb_dev && may_use_hifi_record) {
5123 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5124 in->config = pcm_config_audio_capture;
5125 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005126 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5127 config->sample_rate,
5128 config->format,
5129 channel_count,
5130 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005131 in->config.period_size = buffer_size / frame_size;
5132 in->config.rate = config->sample_rate;
5133 in->af_period_multiplier = 1;
5134 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005135 } else {
5136 in->usecase = USECASE_AUDIO_RECORD;
5137 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005138 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005139 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005140#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005141 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005142#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005143 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005144 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005145 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005146 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005147 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5148 config->sample_rate,
5149 config->format,
5150 channel_count,
5151 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005152 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005153 in->config.rate = config->sample_rate;
5154 in->af_period_multiplier = 1;
5155 } else {
5156 // period size is left untouched for rt mode playback
5157 in->config = pcm_config_audio_capture_rt;
5158 in->af_period_multiplier = af_period_multiplier;
5159 }
5160 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5161 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005162 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005163 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5164 in->config = pcm_config_mmap_capture;
5165 in->stream.start = in_start;
5166 in->stream.stop = in_stop;
5167 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5168 in->stream.get_mmap_position = in_get_mmap_position;
5169 in->af_period_multiplier = 1;
5170 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005171 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005172 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005173 (config->sample_rate == 8000 ||
5174 config->sample_rate == 16000 ||
5175 config->sample_rate == 32000 ||
5176 config->sample_rate == 48000) &&
5177 channel_count == 1) {
5178 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5179 in->config = pcm_config_audio_capture;
5180 frame_size = audio_stream_in_frame_size(&in->stream);
5181 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5182 config->sample_rate,
5183 config->format,
5184 channel_count, false /*is_low_latency*/);
5185 in->config.period_size = buffer_size / frame_size;
5186 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5187 in->config.rate = config->sample_rate;
5188 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005189 } else {
5190 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005191 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005192 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5193 config->sample_rate,
5194 config->format,
5195 channel_count,
5196 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005197 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005198 in->config.rate = config->sample_rate;
5199 in->af_period_multiplier = 1;
5200 }
5201 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5202 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005203 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005206 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207
Kevin Rocarda325aa22018-04-03 09:15:52 -07005208
5209 register_format(in->format, in->supported_formats);
5210 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5211 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5212
Andy Hungd13f0d32017-06-12 13:58:37 -07005213 in->error_log = error_log_create(
5214 ERROR_LOG_ENTRIES,
5215 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5216
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005217 /* This stream could be for sound trigger lab,
5218 get sound trigger pcm if present */
5219 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005220
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005221 lock_input_stream(in);
5222 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5223 pthread_mutex_lock(&adev->lock);
5224 in->card_status = adev->card_status;
5225 pthread_mutex_unlock(&adev->lock);
5226 pthread_mutex_unlock(&in->lock);
5227
vivek mehta4a824772017-06-08 19:05:49 -07005228 stream_app_type_cfg_init(&in->app_type_cfg);
5229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005230 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005231 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005232 return 0;
5233
5234err_open:
5235 free(in);
5236 *stream_in = NULL;
5237 return ret;
5238}
5239
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005240static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241 struct audio_stream_in *stream)
5242{
Andy Hungd13f0d32017-06-12 13:58:37 -07005243 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005244 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005245
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005246 // must deregister from sndmonitor first to prevent races
5247 // between the callback and close_stream
5248 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005250
5251 error_log_destroy(in->error_log);
5252 in->error_log = NULL;
5253
Andy Hung0dbb52b2017-08-09 13:51:38 -07005254 pthread_mutex_destroy(&in->pre_lock);
5255 pthread_mutex_destroy(&in->lock);
5256
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005257 free(stream);
5258
5259 return;
5260}
5261
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005262static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005263{
5264 return 0;
5265}
5266
Andy Hung31aca912014-03-20 17:14:59 -07005267/* verifies input and output devices and their capabilities.
5268 *
5269 * This verification is required when enabling extended bit-depth or
5270 * sampling rates, as not all qcom products support it.
5271 *
5272 * Suitable for calling only on initialization such as adev_open().
5273 * It fills the audio_device use_case_table[] array.
5274 *
5275 * Has a side-effect that it needs to configure audio routing / devices
5276 * in order to power up the devices and read the device parameters.
5277 * It does not acquire any hw device lock. Should restore the devices
5278 * back to "normal state" upon completion.
5279 */
5280static int adev_verify_devices(struct audio_device *adev)
5281{
5282 /* enumeration is a bit difficult because one really wants to pull
5283 * the use_case, device id, etc from the hidden pcm_device_table[].
5284 * In this case there are the following use cases and device ids.
5285 *
5286 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5287 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005288 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005289 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5290 * [USECASE_AUDIO_RECORD] = {0, 0},
5291 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5292 * [USECASE_VOICE_CALL] = {2, 2},
5293 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005294 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005295 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5296 */
5297
5298 /* should be the usecases enabled in adev_open_input_stream() */
5299 static const int test_in_usecases[] = {
5300 USECASE_AUDIO_RECORD,
5301 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5302 };
5303 /* should be the usecases enabled in adev_open_output_stream()*/
5304 static const int test_out_usecases[] = {
5305 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5306 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5307 };
5308 static const usecase_type_t usecase_type_by_dir[] = {
5309 PCM_PLAYBACK,
5310 PCM_CAPTURE,
5311 };
5312 static const unsigned flags_by_dir[] = {
5313 PCM_OUT,
5314 PCM_IN,
5315 };
5316
5317 size_t i;
5318 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005319 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005320 char info[512]; /* for possible debug info */
5321
5322 for (dir = 0; dir < 2; ++dir) {
5323 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5324 const unsigned flags_dir = flags_by_dir[dir];
5325 const size_t testsize =
5326 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5327 const int *testcases =
5328 dir ? test_in_usecases : test_out_usecases;
5329 const audio_devices_t audio_device =
5330 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5331
5332 for (i = 0; i < testsize; ++i) {
5333 const audio_usecase_t audio_usecase = testcases[i];
5334 int device_id;
5335 snd_device_t snd_device;
5336 struct pcm_params **pparams;
5337 struct stream_out out;
5338 struct stream_in in;
5339 struct audio_usecase uc_info;
5340 int retval;
5341
5342 pparams = &adev->use_case_table[audio_usecase];
5343 pcm_params_free(*pparams); /* can accept null input */
5344 *pparams = NULL;
5345
5346 /* find the device ID for the use case (signed, for error) */
5347 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5348 if (device_id < 0)
5349 continue;
5350
5351 /* prepare structures for device probing */
5352 memset(&uc_info, 0, sizeof(uc_info));
5353 uc_info.id = audio_usecase;
5354 uc_info.type = usecase_type;
5355 if (dir) {
5356 adev->active_input = &in;
5357 memset(&in, 0, sizeof(in));
5358 in.device = audio_device;
5359 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5360 uc_info.stream.in = &in;
5361 } else {
5362 adev->active_input = NULL;
5363 }
5364 memset(&out, 0, sizeof(out));
5365 out.devices = audio_device; /* only field needed in select_devices */
5366 uc_info.stream.out = &out;
5367 uc_info.devices = audio_device;
5368 uc_info.in_snd_device = SND_DEVICE_NONE;
5369 uc_info.out_snd_device = SND_DEVICE_NONE;
5370 list_add_tail(&adev->usecase_list, &uc_info.list);
5371
5372 /* select device - similar to start_(in/out)put_stream() */
5373 retval = select_devices(adev, audio_usecase);
5374 if (retval >= 0) {
5375 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5376#if LOG_NDEBUG == 0
5377 if (*pparams) {
5378 ALOGV("%s: (%s) card %d device %d", __func__,
5379 dir ? "input" : "output", card_id, device_id);
5380 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005381 } else {
5382 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5383 }
5384#endif
5385 }
5386
5387 /* deselect device - similar to stop_(in/out)put_stream() */
5388 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005389 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005390 /* 2. Disable the rx device */
5391 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005392 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005393 list_remove(&uc_info.list);
5394 }
5395 }
5396 adev->active_input = NULL; /* restore adev state */
5397 return 0;
5398}
5399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400static int adev_close(hw_device_t *device)
5401{
Andy Hung31aca912014-03-20 17:14:59 -07005402 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005403 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005404
5405 if (!adev)
5406 return 0;
5407
5408 pthread_mutex_lock(&adev_init_lock);
5409
5410 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005411 audio_extn_snd_mon_unregister_listener(adev);
5412 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005413 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005414 audio_route_free(adev->audio_route);
5415 free(adev->snd_dev_ref_cnt);
5416 platform_deinit(adev->platform);
5417 audio_extn_extspk_deinit(adev->extspk);
5418 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005419 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005420 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5421 pcm_params_free(adev->use_case_table[i]);
5422 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005423 if (adev->adm_deinit)
5424 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005425 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005426 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005427 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005428
5429 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005431 return 0;
5432}
5433
Glenn Kasten4f993392014-05-14 07:30:48 -07005434/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5435 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5436 * just that it _might_ work.
5437 */
5438static int period_size_is_plausible_for_low_latency(int period_size)
5439{
5440 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005441 case 48:
5442 case 96:
5443 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005444 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005445 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005446 case 240:
5447 case 320:
5448 case 480:
5449 return 1;
5450 default:
5451 return 0;
5452 }
5453}
5454
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005455static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5456{
5457 int card;
5458 card_status_t status;
5459
5460 if (!parms)
5461 return;
5462
5463 if (parse_snd_card_status(parms, &card, &status) < 0)
5464 return;
5465
5466 pthread_mutex_lock(&adev->lock);
5467 bool valid_cb = (card == adev->snd_card);
5468 if (valid_cb) {
5469 if (adev->card_status != status) {
5470 adev->card_status = status;
5471 platform_snd_card_update(adev->platform, status);
5472 }
5473 }
5474 pthread_mutex_unlock(&adev->lock);
5475 return;
5476}
5477
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005478/* out and adev lock held */
5479static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5480{
5481 struct audio_usecase *uc_info;
5482 float left_p;
5483 float right_p;
5484 audio_devices_t devices;
5485
5486 uc_info = get_usecase_from_list(adev, out->usecase);
5487 if (uc_info == NULL) {
5488 ALOGE("%s: Could not find the usecase (%d) in the list",
5489 __func__, out->usecase);
5490 return -EINVAL;
5491 }
5492
5493 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5494 out->usecase, use_case_table[out->usecase]);
5495
5496 if (restore) {
5497 // restore A2DP device for active usecases and unmute if required
5498 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5499 !is_a2dp_device(uc_info->out_snd_device)) {
5500 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5501 select_devices(adev, uc_info->id);
5502 pthread_mutex_lock(&out->compr_mute_lock);
5503 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5504 (out->a2dp_compress_mute)) {
5505 out->a2dp_compress_mute = false;
5506 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5507 }
5508 pthread_mutex_unlock(&out->compr_mute_lock);
5509 }
5510 } else {
5511 // mute compress stream if suspended
5512 pthread_mutex_lock(&out->compr_mute_lock);
5513 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5514 (!out->a2dp_compress_mute)) {
5515 if (!out->standby) {
5516 ALOGD("%s: selecting speaker and muting stream", __func__);
5517 devices = out->devices;
5518 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5519 left_p = out->volume_l;
5520 right_p = out->volume_r;
5521 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5522 compress_pause(out->compr);
5523 set_compr_volume(&out->stream, 0.0f, 0.0f);
5524 out->a2dp_compress_mute = true;
5525 select_devices(adev, out->usecase);
5526 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5527 compress_resume(out->compr);
5528 out->devices = devices;
5529 out->volume_l = left_p;
5530 out->volume_r = right_p;
5531 }
5532 }
5533 pthread_mutex_unlock(&out->compr_mute_lock);
5534 }
5535 ALOGV("%s: exit", __func__);
5536 return 0;
5537}
5538
5539int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5540{
5541 int ret = 0;
5542
5543 lock_output_stream(out);
5544 pthread_mutex_lock(&adev->lock);
5545
5546 ret = check_a2dp_restore_l(adev, out, restore);
5547
5548 pthread_mutex_unlock(&adev->lock);
5549 pthread_mutex_unlock(&out->lock);
5550 return ret;
5551}
5552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005553static int adev_open(const hw_module_t *module, const char *name,
5554 hw_device_t **device)
5555{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005556 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005557
Eric Laurent2bafff12016-03-17 12:17:23 -07005558 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005559 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005560 pthread_mutex_lock(&adev_init_lock);
5561 if (audio_device_ref_count != 0) {
5562 *device = &adev->device.common;
5563 audio_device_ref_count++;
5564 ALOGV("%s: returning existing instance of adev", __func__);
5565 ALOGV("%s: exit", __func__);
5566 pthread_mutex_unlock(&adev_init_lock);
5567 return 0;
5568 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569 adev = calloc(1, sizeof(struct audio_device));
5570
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005571 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5574 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5575 adev->device.common.module = (struct hw_module_t *)module;
5576 adev->device.common.close = adev_close;
5577
5578 adev->device.init_check = adev_init_check;
5579 adev->device.set_voice_volume = adev_set_voice_volume;
5580 adev->device.set_master_volume = adev_set_master_volume;
5581 adev->device.get_master_volume = adev_get_master_volume;
5582 adev->device.set_master_mute = adev_set_master_mute;
5583 adev->device.get_master_mute = adev_get_master_mute;
5584 adev->device.set_mode = adev_set_mode;
5585 adev->device.set_mic_mute = adev_set_mic_mute;
5586 adev->device.get_mic_mute = adev_get_mic_mute;
5587 adev->device.set_parameters = adev_set_parameters;
5588 adev->device.get_parameters = adev_get_parameters;
5589 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5590 adev->device.open_output_stream = adev_open_output_stream;
5591 adev->device.close_output_stream = adev_close_output_stream;
5592 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005594 adev->device.close_input_stream = adev_close_input_stream;
5595 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005596 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005597
5598 /* Set the default route before the PCM stream is opened */
5599 pthread_mutex_lock(&adev->lock);
5600 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005601 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005602 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005603 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005604 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005605 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005606 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005607 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005608 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005609 pthread_mutex_unlock(&adev->lock);
5610
5611 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005612 adev->platform = platform_init(adev);
5613 if (!adev->platform) {
5614 free(adev->snd_dev_ref_cnt);
5615 free(adev);
5616 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5617 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005618 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005619 return -EINVAL;
5620 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005621 adev->extspk = audio_extn_extspk_init(adev);
5622
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005623 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5624 if (adev->visualizer_lib == NULL) {
5625 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5626 } else {
5627 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5628 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005629 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005630 "visualizer_hal_start_output");
5631 adev->visualizer_stop_output =
5632 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5633 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005634 }
5635
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005636 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5637 if (adev->offload_effects_lib == NULL) {
5638 ALOGW("%s: DLOPEN failed for %s", __func__,
5639 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5640 } else {
5641 ALOGV("%s: DLOPEN successful for %s", __func__,
5642 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5643 adev->offload_effects_start_output =
5644 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5645 "offload_effects_bundle_hal_start_output");
5646 adev->offload_effects_stop_output =
5647 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5648 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005649 }
5650
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005651 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5652 if (adev->adm_lib == NULL) {
5653 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5654 } else {
5655 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5656 adev->adm_init = (adm_init_t)
5657 dlsym(adev->adm_lib, "adm_init");
5658 adev->adm_deinit = (adm_deinit_t)
5659 dlsym(adev->adm_lib, "adm_deinit");
5660 adev->adm_register_input_stream = (adm_register_input_stream_t)
5661 dlsym(adev->adm_lib, "adm_register_input_stream");
5662 adev->adm_register_output_stream = (adm_register_output_stream_t)
5663 dlsym(adev->adm_lib, "adm_register_output_stream");
5664 adev->adm_deregister_stream = (adm_deregister_stream_t)
5665 dlsym(adev->adm_lib, "adm_deregister_stream");
5666 adev->adm_request_focus = (adm_request_focus_t)
5667 dlsym(adev->adm_lib, "adm_request_focus");
5668 adev->adm_abandon_focus = (adm_abandon_focus_t)
5669 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005670 adev->adm_set_config = (adm_set_config_t)
5671 dlsym(adev->adm_lib, "adm_set_config");
5672 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5673 dlsym(adev->adm_lib, "adm_request_focus_v2");
5674 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5675 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5676 adev->adm_on_routing_change = (adm_on_routing_change_t)
5677 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005678 }
5679
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005680 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005681 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005683 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005684
Andy Hung31aca912014-03-20 17:14:59 -07005685 if (k_enable_extended_precision)
5686 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687
Glenn Kasten4f993392014-05-14 07:30:48 -07005688 char value[PROPERTY_VALUE_MAX];
5689 int trial;
5690 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5691 trial = atoi(value);
5692 if (period_size_is_plausible_for_low_latency(trial)) {
5693 pcm_config_low_latency.period_size = trial;
5694 pcm_config_low_latency.start_threshold = trial / 4;
5695 pcm_config_low_latency.avail_min = trial / 4;
5696 configured_low_latency_capture_period_size = trial;
5697 }
5698 }
5699 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5700 trial = atoi(value);
5701 if (period_size_is_plausible_for_low_latency(trial)) {
5702 configured_low_latency_capture_period_size = trial;
5703 }
5704 }
5705
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005706 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5707
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005708 // commented as full set of app type cfg is sent from platform
5709 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005710 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005711
5712 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5713 af_period_multiplier = atoi(value);
5714 if (af_period_multiplier < 0) {
5715 af_period_multiplier = 2;
5716 } else if (af_period_multiplier > 4) {
5717 af_period_multiplier = 4;
5718 }
5719 ALOGV("new period_multiplier = %d", af_period_multiplier);
5720 }
5721
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005722 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005723 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005724
vivek mehta1a9b7c02015-06-25 11:49:38 -07005725 pthread_mutex_unlock(&adev_init_lock);
5726
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005727 if (adev->adm_init)
5728 adev->adm_data = adev->adm_init();
5729
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005730 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005731 audio_extn_snd_mon_init();
5732 pthread_mutex_lock(&adev->lock);
5733 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5734 adev->card_status = CARD_STATUS_ONLINE;
5735 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005736 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005737
Eric Laurent2bafff12016-03-17 12:17:23 -07005738 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005739 return 0;
5740}
5741
5742static struct hw_module_methods_t hal_module_methods = {
5743 .open = adev_open,
5744};
5745
5746struct audio_module HAL_MODULE_INFO_SYM = {
5747 .common = {
5748 .tag = HARDWARE_MODULE_TAG,
5749 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5750 .hal_api_version = HARDWARE_HAL_API_VERSION,
5751 .id = AUDIO_HARDWARE_MODULE_ID,
5752 .name = "QCOM Audio HAL",
5753 .author = "Code Aurora Forum",
5754 .methods = &hal_module_methods,
5755 },
5756};